1*8345Ssam static char sccsid[] = "@(#)telnet.c 4.9 (Berkeley) 10/06/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> 14*8345Ssam #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; 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; 397377Sfeldman int options; 406000Sroot char *prompt; 417377Sfeldman 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(); 536024Ssam 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"; 706024Ssam 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 }, 796024Ssam { "options", phelp, setoptions }, 806000Sroot { "?", hhelp, help }, 816000Sroot 0 826000Sroot }; 836000Sroot 84*8345Ssam struct sockaddr_in sin = { AF_INET }; 856000Sroot 866000Sroot int intr(), deadpeer(); 876000Sroot char *control(); 886000Sroot struct cmd *getcmd(); 89*8345Ssam struct servent *sp; 906000Sroot 916000Sroot main(argc, argv) 926000Sroot int argc; 936000Sroot char *argv[]; 946000Sroot { 95*8345Ssam sp = getservbyname("telnet", "tcp"); 96*8345Ssam if (sp == 0) { 97*8345Ssam fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 98*8345Ssam exit(1); 99*8345Ssam } 1006000Sroot setbuf(stdin, 0); 1016000Sroot setbuf(stdout, 0); 1026000Sroot prompt = argv[0]; 1037377Sfeldman if (argc > 1 && !strcmp(argv[1], "-d")) 1047377Sfeldman options = SO_DEBUG, argv++, argc--; 1056000Sroot if (argc != 1) { 1066000Sroot if (setjmp(toplevel) != 0) 1076000Sroot exit(0); 1086000Sroot tn(argc, argv); 1096000Sroot } 1106000Sroot setjmp(toplevel); 1116000Sroot for (;;) 1126000Sroot command(1); 1136000Sroot } 1146000Sroot 115*8345Ssam struct hostent *host; 1166000Sroot 1176000Sroot tn(argc, argv) 1186000Sroot int argc; 1196000Sroot char *argv[]; 1206000Sroot { 1216000Sroot register int c; 1226000Sroot 1236000Sroot if (connected) { 124*8345Ssam printf("?Already connected to %s\n", host->h_name); 1256000Sroot return; 1266000Sroot } 1276000Sroot if (argc < 2) { 1286000Sroot strcpy(line, "Connect "); 1296000Sroot printf("(to) "); 1306000Sroot gets(&line[strlen(line)]); 1316000Sroot makeargv(); 1326000Sroot argc = margc; 1336000Sroot argv = margv; 1346000Sroot } 1356000Sroot if (argc > 3) { 1366000Sroot printf("usage: %s host-name [port]\n", argv[0]); 1376000Sroot return; 1386000Sroot } 139*8345Ssam host = gethostbyname(argv[1]); 140*8345Ssam if (host == 0) { 1416000Sroot printf("%s: unknown host\n", argv[1]); 1426000Sroot return; 1436000Sroot } 144*8345Ssam bcopy(host->h_addr, &sin.sin_addr, host->h_length); 145*8345Ssam sin.sin_port = sp->s_port; 1466024Ssam if (argc == 3) { 1476024Ssam sin.sin_port = atoi(argv[2]); 1486024Ssam if (sin.sin_port < 0) { 1496024Ssam printf("%s: bad port number\n", argv[2]); 1506024Ssam return; 1516024Ssam } 1526024Ssam } 153*8345Ssam sin.sin_port = htons(sin.sin_port); 1547377Sfeldman if ((net = socket(SOCK_STREAM, 0, 0, options)) < 0) { 1556000Sroot perror("socket"); 1566000Sroot return; 1576000Sroot } 1586000Sroot sigset(SIGINT, intr); 1596000Sroot sigset(SIGPIPE, deadpeer); 1606000Sroot printf("Trying...\n"); 1616000Sroot if (connect(net, &sin)) { 1626000Sroot perror("connect"); 1636000Sroot sigset(SIGINT, SIG_DFL); 1646000Sroot return; 1656000Sroot } 1666000Sroot connected++; 1676000Sroot call(status, "status", 0); 1686000Sroot if (setjmp(peerdied) == 0) 1696000Sroot telnet(net); 1706000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 1716000Sroot exit(1); 1726000Sroot } 1736000Sroot 1746000Sroot /* 1756000Sroot * Print status about the connection. 1766000Sroot */ 1776000Sroot /*VARARGS*/ 1786000Sroot status() 1796000Sroot { 1806000Sroot if (connected) 181*8345Ssam printf("Connected to %s.\n", host->h_name); 1826000Sroot else 1836000Sroot printf("No connection.\n"); 1846000Sroot printf("Escape character is '%s'.\n", control(escape)); 1856000Sroot } 1866000Sroot 1876000Sroot makeargv() 1886000Sroot { 1896000Sroot register char *cp; 1906000Sroot register char **argp = margv; 1916000Sroot 1926000Sroot margc = 0; 1936000Sroot for (cp = line; *cp;) { 1946000Sroot while (isspace(*cp)) 1956000Sroot cp++; 1966000Sroot if (*cp == '\0') 1976000Sroot break; 1986000Sroot *argp++ = cp; 1996000Sroot margc += 1; 2006000Sroot while (*cp != '\0' && !isspace(*cp)) 2016000Sroot cp++; 2026000Sroot if (*cp == '\0') 2036000Sroot break; 2046000Sroot *cp++ = '\0'; 2056000Sroot } 2066000Sroot *argp++ = 0; 2076000Sroot } 2086000Sroot 2096000Sroot /*VARARGS*/ 2106000Sroot suspend() 2116000Sroot { 2126000Sroot register int save; 2136000Sroot 2146000Sroot save = mode(0); 2156000Sroot kill(0, SIGTSTP); /* get whole process group */ 2166000Sroot mode(save); 2176000Sroot } 2186000Sroot 2196000Sroot /*VARARGS*/ 2206000Sroot bye() 2216000Sroot { 2226000Sroot int how = 2; 2236000Sroot 2246000Sroot mode(0); 2256000Sroot if (connected) { 2266000Sroot ioctl(net, SIOCDONE, &how); 2276000Sroot printf("Connection closed.\n"); 2286000Sroot close(net); 2296000Sroot connected = 0; 2306000Sroot } 2316000Sroot } 2326000Sroot 2336000Sroot /*VARARGS*/ 2346000Sroot quit() 2356000Sroot { 2366000Sroot call(bye, "bye", 0); 2376000Sroot exit(0); 2386000Sroot } 2396000Sroot 2406000Sroot /* 2416000Sroot * Help command. 2426000Sroot * Call each command handler with argc == 0 and argv[0] == name. 2436000Sroot */ 2446000Sroot help(argc, argv) 2456000Sroot int argc; 2466000Sroot char *argv[]; 2476000Sroot { 2486000Sroot register struct cmd *c; 2496000Sroot 2506000Sroot if (argc == 1) { 2516000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 2526000Sroot for (c = cmdtab; c->name; c++) 2536000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 2546000Sroot return; 2556000Sroot } 2566000Sroot while (--argc > 0) { 2576000Sroot register char *arg; 2586000Sroot arg = *++argv; 2596000Sroot c = getcmd(arg); 2606000Sroot if (c == (struct cmd *)-1) 2616000Sroot printf("?Ambiguous help command %s\n", arg); 2626000Sroot else if (c == (struct cmd *)0) 2636000Sroot printf("?Invalid help command %s\n", arg); 2646000Sroot else 2656000Sroot printf("%s\n", c->help); 2666000Sroot } 2676000Sroot } 2686000Sroot 2696000Sroot /* 2706000Sroot * Call routine with argc, argv set from args (terminated by 0). 2716000Sroot * VARARGS2 2726000Sroot */ 2736000Sroot call(routine, args) 2746000Sroot int (*routine)(); 2756000Sroot int args; 2766000Sroot { 2776000Sroot register int *argp; 2786000Sroot register int argc; 2796000Sroot 2806000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 2816000Sroot ; 2826000Sroot (*routine)(argc, &args); 2836000Sroot } 2846000Sroot 2856000Sroot mode(f) 2866000Sroot register int f; 2876000Sroot { 2886000Sroot register int old; 2896000Sroot struct sgttyb stbuf; 2906000Sroot static int ttymode = 0; 2916000Sroot int onoff; 2926000Sroot 2936000Sroot ioctl(fileno(stdin), TIOCGETP, &stbuf); 2946000Sroot old = ttymode; 2956000Sroot ttymode = f; 2966000Sroot switch (f) { 2976000Sroot case 0: 2986000Sroot stbuf.sg_flags &= ~RAW; 2996000Sroot stbuf.sg_flags |= ECHO|CRMOD; 3006000Sroot onoff = 0; 3016000Sroot break; 3026000Sroot 3036000Sroot case 1: 3046000Sroot stbuf.sg_flags |= RAW; 3056000Sroot stbuf.sg_flags &= ~(ECHO|CRMOD); 3066000Sroot onoff = 1; 3076000Sroot break; 3086000Sroot 3096000Sroot case 2: 3106000Sroot stbuf.sg_flags |= RAW; 3116000Sroot stbuf.sg_flags |= ECHO|CRMOD; 3126000Sroot onoff = 1; 3136000Sroot } 3146000Sroot ioctl(fileno(stdin), TIOCSETN, &stbuf); 3156000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 3166000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 3176000Sroot return (old); 3186000Sroot } 3196000Sroot 3206000Sroot char sibuf[BUFSIZ], *sbp; 3216000Sroot char tibuf[BUFSIZ], *tbp; 3226000Sroot int scc, tcc; 3236000Sroot 3246000Sroot /* 3256000Sroot * Select from tty and network... 3266000Sroot */ 3276000Sroot telnet(s) 3286000Sroot int s; 3296000Sroot { 3306000Sroot register int c; 3316000Sroot int tin = fileno(stdin), tout = fileno(stdout); 3326000Sroot int on = 1; 3336000Sroot 3346000Sroot mode(1); 335*8345Ssam printoption("SENT", doopt, TELOPT_ECHO); 3366000Sroot sprintf(nfrontp, doopt, TELOPT_ECHO); 3376000Sroot nfrontp += sizeof(doopt) - 2; 3386389Ssam hisopts[TELOPT_ECHO] = 1; 339*8345Ssam printoption("SENT", doopt, TELOPT_SGA); 3406000Sroot sprintf(nfrontp, doopt, TELOPT_SGA); 3416000Sroot nfrontp += sizeof(doopt) - 2; 3426389Ssam hisopts[TELOPT_SGA] = 1; 343*8345Ssam printoption("SENT", will, TELOPT_SGA); 3446000Sroot sprintf(nfrontp, will, TELOPT_SGA); 3456000Sroot nfrontp += sizeof(doopt) - 2; 3466389Ssam myopts[TELOPT_SGA] = 1; 3476000Sroot ioctl(s, FIONBIO, &on); 3486000Sroot for (;;) { 3496000Sroot int ibits = 0, obits = 0; 3506000Sroot 3516000Sroot if (nfrontp - nbackp) 3526000Sroot obits |= (1 << s); 3536000Sroot else 3546000Sroot ibits |= (1 << tin); 3556000Sroot if (tfrontp - tbackp) 3566000Sroot obits |= (1 << tout); 3576000Sroot else 3586000Sroot ibits |= (1 << s); 3596000Sroot if (scc < 0 && tcc < 0) 3606000Sroot break; 3616000Sroot select(32, &ibits, &obits, INFINITY); 3626000Sroot if (ibits == 0 && obits == 0) { 3636000Sroot sleep(5); 3646000Sroot continue; 3656000Sroot } 3666000Sroot 3676000Sroot /* 3686000Sroot * Something to read from the network... 3696000Sroot */ 3706000Sroot if (ibits & (1 << s)) { 3716000Sroot scc = read(s, sibuf, sizeof(sibuf)); 3726000Sroot if (scc < 0 && errno == EWOULDBLOCK) 3736000Sroot scc = 0; 3746000Sroot else { 3756000Sroot if (scc <= 0) 3766000Sroot break; 3776000Sroot sbp = sibuf; 3786000Sroot } 3796000Sroot } 3806000Sroot 3816000Sroot /* 3826000Sroot * Something to read from the tty... 3836000Sroot */ 3846000Sroot if (ibits & (1 << tin)) { 3856000Sroot tcc = read(tin, tibuf, sizeof(tibuf)); 3866000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 3876000Sroot tcc = 0; 3886000Sroot else { 3896000Sroot if (tcc <= 0) 3906000Sroot break; 3916000Sroot tbp = tibuf; 3926000Sroot } 3936000Sroot } 3946000Sroot 3956000Sroot while (tcc > 0) { 3966000Sroot register int c; 3976000Sroot 3986000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 3996000Sroot break; 4006000Sroot c = *tbp++ & 0377, tcc--; 4016000Sroot if (strip(c) == escape) { 4026000Sroot command(0); 4036000Sroot tcc = 0; 4046000Sroot break; 4056000Sroot } 4066000Sroot *nfrontp++ = c; 4076000Sroot } 4086000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 4096000Sroot netflush(s); 4106000Sroot if (scc > 0) 4116000Sroot telrcv(); 4126000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4136000Sroot ttyflush(tout); 4146000Sroot } 4156000Sroot mode(0); 4166000Sroot } 4176000Sroot 4186000Sroot command(top) 4196000Sroot int top; 4206000Sroot { 4216000Sroot register struct cmd *c; 4226000Sroot int oldmode, wasopen; 4236000Sroot 4246000Sroot oldmode = mode(0); 4256000Sroot if (!top) 4266000Sroot putchar('\n'); 4276000Sroot else 4286000Sroot sigset(SIGINT, SIG_DFL); 4296000Sroot for (;;) { 4306000Sroot printf("%s> ", prompt); 4316000Sroot if (gets(line) == 0) 4326000Sroot break; 4336000Sroot if (line[0] == 0) 4346000Sroot break; 4356000Sroot makeargv(); 4366000Sroot c = getcmd(margv[0]); 4376000Sroot if (c == (struct cmd *)-1) { 4386000Sroot printf("?Ambiguous command\n"); 4396000Sroot continue; 4406000Sroot } 4416000Sroot if (c == 0) { 4426000Sroot printf("?Invalid command\n"); 4436000Sroot continue; 4446000Sroot } 4456000Sroot (*c->handler)(margc, margv); 4466000Sroot if (c->handler != help) 4476000Sroot break; 4486000Sroot } 4496000Sroot if (!top) { 4506000Sroot if (!connected) 4516000Sroot longjmp(toplevel, 1); 4526000Sroot mode(oldmode); 4536000Sroot } 4546000Sroot } 4556000Sroot 4566000Sroot /* 4576000Sroot * Telnet receiver states for fsm 4586000Sroot */ 4596000Sroot #define TS_DATA 0 4606000Sroot #define TS_IAC 1 4616000Sroot #define TS_WILL 2 4626000Sroot #define TS_WONT 3 4636000Sroot #define TS_DO 4 4646000Sroot #define TS_DONT 5 4656000Sroot 4666000Sroot telrcv() 4676000Sroot { 4686000Sroot register int c; 4696000Sroot static int state = TS_DATA; 4706000Sroot 4716000Sroot while (scc > 0) { 4726000Sroot c = *sbp++ & 0377, scc--; 4736000Sroot switch (state) { 4746000Sroot 4756000Sroot case TS_DATA: 4766000Sroot if (c == IAC) 4776000Sroot state = TS_IAC; 4786000Sroot else 4796000Sroot *tfrontp++ = c; 4806000Sroot continue; 4816000Sroot 4826000Sroot case TS_IAC: 4836000Sroot switch (c) { 4846000Sroot 4856000Sroot case WILL: 4866000Sroot state = TS_WILL; 4876000Sroot continue; 4886000Sroot 4896000Sroot case WONT: 4906000Sroot state = TS_WONT; 4916000Sroot continue; 4926000Sroot 4936000Sroot case DO: 4946000Sroot state = TS_DO; 4956000Sroot continue; 4966000Sroot 4976000Sroot case DONT: 4986000Sroot state = TS_DONT; 4996000Sroot continue; 5006000Sroot 5016000Sroot case DM: 5026000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 5036000Sroot break; 5046000Sroot 5056000Sroot case NOP: 5066000Sroot case GA: 5076000Sroot break; 5086000Sroot 5096000Sroot default: 5106000Sroot break; 5116000Sroot } 5126000Sroot state = TS_DATA; 5136000Sroot continue; 5146000Sroot 5156000Sroot case TS_WILL: 516*8345Ssam printoption("RCVD", will, c, !hisopts[c]); 5176000Sroot if (!hisopts[c]) 5186000Sroot willoption(c); 5196000Sroot state = TS_DATA; 5206000Sroot continue; 5216000Sroot 5226000Sroot case TS_WONT: 523*8345Ssam printoption("RCVD", wont, c, hisopts[c]); 5246000Sroot if (hisopts[c]) 5256000Sroot wontoption(c); 5266000Sroot state = TS_DATA; 5276000Sroot continue; 5286000Sroot 5296000Sroot case TS_DO: 530*8345Ssam printoption("RCVD", doopt, c, !myopts[c]); 5316000Sroot if (!myopts[c]) 5326000Sroot dooption(c); 5336000Sroot state = TS_DATA; 5346000Sroot continue; 5356000Sroot 5366000Sroot case TS_DONT: 537*8345Ssam printoption("RCVD", dont, c, myopts[c]); 5386000Sroot if (myopts[c]) { 5396000Sroot myopts[c] = 0; 5406000Sroot sprintf(nfrontp, wont, c); 5416000Sroot nfrontp += sizeof(wont) - 2; 542*8345Ssam printoption("SENT", wont, c); 5436000Sroot } 5446000Sroot state = TS_DATA; 5456000Sroot continue; 5466000Sroot } 5476000Sroot } 5486000Sroot } 5496000Sroot 5506000Sroot willoption(option) 5516000Sroot int option; 5526000Sroot { 5536000Sroot char *fmt; 5546000Sroot 5556000Sroot switch (option) { 5566000Sroot 5576000Sroot case TELOPT_ECHO: 5586000Sroot mode(1); 5596000Sroot 5606000Sroot case TELOPT_SGA: 5616000Sroot hisopts[option] = 1; 5626000Sroot fmt = doopt; 5636000Sroot break; 5646000Sroot 5656000Sroot case TELOPT_TM: 5666000Sroot fmt = dont; 5676000Sroot break; 5686000Sroot 5696000Sroot default: 5706000Sroot fmt = dont; 5716000Sroot break; 5726000Sroot } 5736024Ssam sprintf(nfrontp, fmt, option); 5746000Sroot nfrontp += sizeof(dont) - 2; 575*8345Ssam printoption("SENT", fmt, option); 5766000Sroot } 5776000Sroot 5786000Sroot wontoption(option) 5796000Sroot int option; 5806000Sroot { 5816000Sroot char *fmt; 5826000Sroot 5836000Sroot switch (option) { 5846000Sroot 5856000Sroot case TELOPT_ECHO: 5866000Sroot mode(2); 5876000Sroot 5886000Sroot case TELOPT_SGA: 5896000Sroot hisopts[option] = 0; 5906000Sroot fmt = dont; 5916000Sroot break; 5926000Sroot 5936000Sroot default: 5946000Sroot fmt = dont; 5956000Sroot } 5966000Sroot sprintf(nfrontp, fmt, option); 5976000Sroot nfrontp += sizeof(doopt) - 2; 598*8345Ssam printoption("SENT", fmt, option); 5996000Sroot } 6006000Sroot 6016000Sroot dooption(option) 6026000Sroot int option; 6036000Sroot { 6046000Sroot char *fmt; 6056000Sroot 6066000Sroot switch (option) { 6076000Sroot 6086000Sroot case TELOPT_TM: 6096000Sroot fmt = wont; 6106000Sroot break; 6116000Sroot 6126000Sroot case TELOPT_SGA: 6136000Sroot fmt = will; 6146000Sroot break; 6156000Sroot 6166000Sroot default: 6176000Sroot fmt = wont; 6186000Sroot break; 6196000Sroot } 6206000Sroot sprintf(nfrontp, fmt, option); 6216000Sroot nfrontp += sizeof(doopt) - 2; 622*8345Ssam printoption("SENT", 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); 726*8345Ssam if (n < 0) 727*8345Ssam return; 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); 7396501Ssam if (n < 0) { 7406501Ssam if (errno != ENOBUFS && errno != EWOULDBLOCK) { 7416501Ssam mode(0); 742*8345Ssam perror(host->h_name); 7436501Ssam close(fd); 7446501Ssam longjmp(peerdied, -1); 7456501Ssam /*NOTREACHED*/ 7466501Ssam } 7476000Sroot n = 0; 7486501Ssam } 7496000Sroot nbackp += n; 7506000Sroot if (nbackp == nfrontp) 7516000Sroot nbackp = nfrontp = netobuf; 7526000Sroot } 7536024Ssam 7546293Sroot /*VARARGS*/ 7556293Sroot printoption(direction, fmt, option, what) 7566024Ssam char *direction, *fmt; 7576293Sroot int option, what; 7586024Ssam { 759*8345Ssam if (!showoptions) 760*8345Ssam return; 7616024Ssam printf("%s ", direction); 7626024Ssam if (fmt == doopt) 7636024Ssam fmt = "do"; 7646024Ssam else if (fmt == dont) 7656024Ssam fmt = "dont"; 7666024Ssam else if (fmt == will) 7676024Ssam fmt = "will"; 7686024Ssam else if (fmt == wont) 7696024Ssam fmt = "wont"; 7706024Ssam else 7716024Ssam fmt = "???"; 7726024Ssam if (option < TELOPT_SUPDUP) 7736293Sroot printf("%s %s", fmt, telopts[option]); 7746024Ssam else 7756293Sroot printf("%s %d", fmt, option); 7766293Sroot if (*direction == '<') { 7776293Sroot printf("\r\n"); 7786293Sroot return; 7796293Sroot } 7806293Sroot printf(" (%s)\r\n", what ? "reply" : "don't reply"); 7816024Ssam } 782