111758Ssam #ifndef lint 2*17484Sleres static char sccsid[] = "@(#)telnet.c 4.25 (Berkeley) 12/06/84"; 311758Ssam #endif 411758Ssam 56000Sroot /* 66000Sroot * User telnet program. 76000Sroot */ 89217Ssam #include <sys/types.h> 99217Ssam #include <sys/socket.h> 109972Ssam #include <sys/ioctl.h> 119217Ssam 129217Ssam #include <netinet/in.h> 139217Ssam 1412212Ssam #define TELOPTS 1512212Ssam #include <arpa/telnet.h> 1612212Ssam 176000Sroot #include <stdio.h> 186000Sroot #include <ctype.h> 196000Sroot #include <errno.h> 206000Sroot #include <signal.h> 216000Sroot #include <setjmp.h> 228345Ssam #include <netdb.h> 239217Ssam 246000Sroot #define strip(x) ((x)&0177) 256000Sroot 266000Sroot char ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf; 278378Ssam char netobuf[BUFSIZ], *nfrontp = netobuf, *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; 399972Ssam int showoptions = 0; 407377Sfeldman int options; 4110339Ssam int debug = 0; 429972Ssam int crmod = 0; 436000Sroot char *prompt; 449972Ssam char escape = CTRL(]); 456000Sroot 466000Sroot char line[200]; 476000Sroot int margc; 486000Sroot char *margv[20]; 496000Sroot 506000Sroot jmp_buf toplevel; 516000Sroot jmp_buf peerdied; 526000Sroot 536000Sroot extern int errno; 546000Sroot 556000Sroot int tn(), quit(), suspend(), bye(), help(); 566024Ssam int setescape(), status(), toggle(), setoptions(); 5710603Ssam int setcrmod(), setdebug(); 586000Sroot 598378Ssam #define HELPINDENT (sizeof ("connect")) 606000Sroot 616000Sroot struct cmd { 6211758Ssam char *name; /* command name */ 6311758Ssam char *help; /* help string */ 6411758Ssam int (*handler)(); /* routine which executes command */ 656000Sroot }; 666000Sroot 6711758Ssam char openhelp[] = "connect to a site"; 6811758Ssam char closehelp[] = "close current connection"; 6911758Ssam char quithelp[] = "exit telnet"; 7011758Ssam char zhelp[] = "suspend telnet"; 7111758Ssam char debughelp[] = "toggle debugging"; 7211758Ssam char escapehelp[] = "set escape character"; 7311758Ssam char statushelp[] = "print status information"; 7411758Ssam char helphelp[] = "print help information"; 7511758Ssam char optionshelp[] = "toggle viewing of options processing"; 7611758Ssam char crmodhelp[] = "toggle mapping of received carriage returns"; 776000Sroot 786000Sroot struct cmd cmdtab[] = { 7911758Ssam { "open", openhelp, tn }, 8011758Ssam { "close", closehelp, bye }, 8111758Ssam { "quit", quithelp, quit }, 826000Sroot { "z", zhelp, suspend }, 8311758Ssam { "escape", escapehelp, setescape }, 8411758Ssam { "status", statushelp, status }, 8511758Ssam { "options", optionshelp, setoptions }, 8611758Ssam { "crmod", crmodhelp, setcrmod }, 8711758Ssam { "debug", debughelp, setdebug }, 8811758Ssam { "?", helphelp, help }, 896000Sroot 0 906000Sroot }; 916000Sroot 929972Ssam struct sockaddr_in sin; 936000Sroot 946000Sroot int intr(), deadpeer(); 956000Sroot char *control(); 966000Sroot struct cmd *getcmd(); 978345Ssam struct servent *sp; 986000Sroot 9913076Ssam struct tchars otc; 10013076Ssam struct ltchars oltc; 10113076Ssam struct sgttyb ottyb; 1028378Ssam 1036000Sroot main(argc, argv) 1046000Sroot int argc; 1056000Sroot char *argv[]; 1066000Sroot { 1078345Ssam sp = getservbyname("telnet", "tcp"); 1088345Ssam if (sp == 0) { 1098345Ssam fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 1108345Ssam exit(1); 1118345Ssam } 11213076Ssam ioctl(0, TIOCGETP, (char *)&ottyb); 11313076Ssam ioctl(0, TIOCGETC, (char *)&otc); 11413076Ssam ioctl(0, TIOCGLTC, (char *)&oltc); 1156000Sroot setbuf(stdin, 0); 1166000Sroot setbuf(stdout, 0); 1176000Sroot prompt = argv[0]; 118*17484Sleres if (argc > 1 && !strcmp(argv[1], "-d")) { 119*17484Sleres debug = 1; 120*17484Sleres argv++; 121*17484Sleres argc--; 122*17484Sleres } 1236000Sroot if (argc != 1) { 1246000Sroot if (setjmp(toplevel) != 0) 1256000Sroot exit(0); 1266000Sroot tn(argc, argv); 1276000Sroot } 1286000Sroot setjmp(toplevel); 1296000Sroot for (;;) 1306000Sroot command(1); 1316000Sroot } 1326000Sroot 1338377Ssam char *hostname; 1348377Ssam char hnamebuf[32]; 1356000Sroot 1366000Sroot tn(argc, argv) 1376000Sroot int argc; 1386000Sroot char *argv[]; 1396000Sroot { 1406000Sroot register int c; 1418377Ssam register struct hostent *host; 1426000Sroot 1436000Sroot if (connected) { 1448377Ssam printf("?Already connected to %s\n", hostname); 1456000Sroot return; 1466000Sroot } 1476000Sroot if (argc < 2) { 1486000Sroot strcpy(line, "Connect "); 1496000Sroot printf("(to) "); 1506000Sroot gets(&line[strlen(line)]); 1516000Sroot makeargv(); 1526000Sroot argc = margc; 1536000Sroot argv = margv; 1546000Sroot } 1556000Sroot if (argc > 3) { 1566000Sroot printf("usage: %s host-name [port]\n", argv[0]); 1576000Sroot return; 1586000Sroot } 1598345Ssam host = gethostbyname(argv[1]); 1608377Ssam if (host) { 1619217Ssam sin.sin_family = host->h_addrtype; 1629217Ssam bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length); 1638377Ssam hostname = host->h_name; 1648377Ssam } else { 1659217Ssam sin.sin_family = AF_INET; 1668377Ssam sin.sin_addr.s_addr = inet_addr(argv[1]); 1678377Ssam if (sin.sin_addr.s_addr == -1) { 1688377Ssam printf("%s: unknown host\n", argv[1]); 1698377Ssam return; 1708377Ssam } 1718377Ssam strcpy(hnamebuf, argv[1]); 1728377Ssam hostname = hnamebuf; 1736000Sroot } 1748345Ssam sin.sin_port = sp->s_port; 1756024Ssam if (argc == 3) { 1766024Ssam sin.sin_port = atoi(argv[2]); 1776024Ssam if (sin.sin_port < 0) { 1786024Ssam printf("%s: bad port number\n", argv[2]); 1796024Ssam return; 1806024Ssam } 1819968Ssam sin.sin_port = htons(sin.sin_port); 1826024Ssam } 1839287Ssam net = socket(AF_INET, SOCK_STREAM, 0, 0); 1849217Ssam if (net < 0) { 1859217Ssam perror("telnet: socket"); 1866000Sroot return; 1876000Sroot } 188*17484Sleres if (debug && 189*17484Sleres setsockopt(net, SOL_SOCKET, SO_DEBUG, &debug, sizeof(debug)) < 0) 19011758Ssam perror("setsockopt (SO_DEBUG)"); 19112989Ssam signal(SIGINT, intr); 19212989Ssam signal(SIGPIPE, deadpeer); 1936000Sroot printf("Trying...\n"); 1949217Ssam if (connect(net, (caddr_t)&sin, sizeof (sin), 0) < 0) { 1959217Ssam perror("telnet: connect"); 19612989Ssam signal(SIGINT, SIG_DFL); 1976000Sroot return; 1986000Sroot } 1996000Sroot connected++; 2006000Sroot call(status, "status", 0); 2016000Sroot if (setjmp(peerdied) == 0) 2026000Sroot telnet(net); 2036000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 2046000Sroot exit(1); 2056000Sroot } 2066000Sroot 2076000Sroot /* 2086000Sroot * Print status about the connection. 2096000Sroot */ 2106000Sroot /*VARARGS*/ 2116000Sroot status() 2126000Sroot { 2136000Sroot if (connected) 2148377Ssam printf("Connected to %s.\n", hostname); 2156000Sroot else 2166000Sroot printf("No connection.\n"); 2176000Sroot printf("Escape character is '%s'.\n", control(escape)); 2189972Ssam fflush(stdout); 2196000Sroot } 2206000Sroot 2216000Sroot makeargv() 2226000Sroot { 2236000Sroot register char *cp; 2246000Sroot register char **argp = margv; 2256000Sroot 2266000Sroot margc = 0; 2276000Sroot for (cp = line; *cp;) { 2286000Sroot while (isspace(*cp)) 2296000Sroot cp++; 2306000Sroot if (*cp == '\0') 2316000Sroot break; 2326000Sroot *argp++ = cp; 2336000Sroot margc += 1; 2346000Sroot while (*cp != '\0' && !isspace(*cp)) 2356000Sroot cp++; 2366000Sroot if (*cp == '\0') 2376000Sroot break; 2386000Sroot *cp++ = '\0'; 2396000Sroot } 2406000Sroot *argp++ = 0; 2416000Sroot } 2426000Sroot 2436000Sroot /*VARARGS*/ 2446000Sroot suspend() 2456000Sroot { 2466000Sroot register int save; 2476000Sroot 2486000Sroot save = mode(0); 2498378Ssam kill(0, SIGTSTP); 2508378Ssam /* reget parameters in case they were changed */ 25113076Ssam ioctl(0, TIOCGETP, (char *)&ottyb); 25213076Ssam ioctl(0, TIOCGETC, (char *)&otc); 25313076Ssam ioctl(0, TIOCGLTC, (char *)&oltc); 2548378Ssam (void) mode(save); 2556000Sroot } 2566000Sroot 2576000Sroot /*VARARGS*/ 2586000Sroot bye() 2596000Sroot { 2608378Ssam register char *op; 2616000Sroot 2628378Ssam (void) mode(0); 2636000Sroot if (connected) { 26411758Ssam shutdown(net, 2); 2656000Sroot printf("Connection closed.\n"); 2666000Sroot close(net); 2676000Sroot connected = 0; 2688378Ssam /* reset his options */ 2698378Ssam for (op = hisopts; op < &hisopts[256]; op++) 2708378Ssam *op = 0; 2716000Sroot } 2726000Sroot } 2736000Sroot 2746000Sroot /*VARARGS*/ 2756000Sroot quit() 2766000Sroot { 2776000Sroot call(bye, "bye", 0); 2786000Sroot exit(0); 2796000Sroot } 2806000Sroot 2816000Sroot /* 2826000Sroot * Help command. 2836000Sroot */ 2846000Sroot help(argc, argv) 2856000Sroot int argc; 2866000Sroot char *argv[]; 2876000Sroot { 2886000Sroot register struct cmd *c; 2896000Sroot 2906000Sroot if (argc == 1) { 2916000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 2926000Sroot for (c = cmdtab; c->name; c++) 2936000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 2946000Sroot return; 2956000Sroot } 2966000Sroot while (--argc > 0) { 2976000Sroot register char *arg; 2986000Sroot arg = *++argv; 2996000Sroot c = getcmd(arg); 3006000Sroot if (c == (struct cmd *)-1) 3016000Sroot printf("?Ambiguous help command %s\n", arg); 3026000Sroot else if (c == (struct cmd *)0) 3036000Sroot printf("?Invalid help command %s\n", arg); 3046000Sroot else 3056000Sroot printf("%s\n", c->help); 3066000Sroot } 3076000Sroot } 3086000Sroot 3096000Sroot /* 3106000Sroot * Call routine with argc, argv set from args (terminated by 0). 3116000Sroot * VARARGS2 3126000Sroot */ 3136000Sroot call(routine, args) 3146000Sroot int (*routine)(); 3156000Sroot int args; 3166000Sroot { 3176000Sroot register int *argp; 3186000Sroot register int argc; 3196000Sroot 3206000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 3216000Sroot ; 3226000Sroot (*routine)(argc, &args); 3236000Sroot } 3246000Sroot 32513076Ssam struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 32613076Ssam struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 3279972Ssam 3286000Sroot mode(f) 3296000Sroot register int f; 3306000Sroot { 3318378Ssam static int prevmode = 0; 33213076Ssam struct tchars *tc; 33313076Ssam struct ltchars *ltc; 33413076Ssam struct sgttyb sb; 33513076Ssam int onoff, old; 3366000Sroot 3378378Ssam if (prevmode == f) 3388378Ssam return (f); 3398378Ssam old = prevmode; 3408378Ssam prevmode = f; 34113076Ssam sb = ottyb; 3426000Sroot switch (f) { 3438378Ssam 3446000Sroot case 0: 3456000Sroot onoff = 0; 3469972Ssam tc = &otc; 34713076Ssam ltc = &oltc; 3486000Sroot break; 3496000Sroot 3506000Sroot case 1: 3516000Sroot case 2: 35213076Ssam sb.sg_flags |= CBREAK; 3538378Ssam if (f == 1) 35413076Ssam sb.sg_flags &= ~(ECHO|CRMOD); 3558378Ssam else 35613076Ssam sb.sg_flags |= ECHO|CRMOD; 35713076Ssam sb.sg_erase = sb.sg_kill = -1; 3589972Ssam tc = ¬c; 35913076Ssam ltc = &noltc; 3606000Sroot onoff = 1; 3619972Ssam break; 3629972Ssam 3639972Ssam default: 3649972Ssam return; 3656000Sroot } 36613076Ssam ioctl(fileno(stdin), TIOCSLTC, (char *)ltc); 36713076Ssam ioctl(fileno(stdin), TIOCSETC, (char *)tc); 36813076Ssam ioctl(fileno(stdin), TIOCSETP, (char *)&sb); 3696000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 3706000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 3716000Sroot return (old); 3726000Sroot } 3736000Sroot 3746000Sroot char sibuf[BUFSIZ], *sbp; 3756000Sroot char tibuf[BUFSIZ], *tbp; 3766000Sroot int scc, tcc; 3776000Sroot 3786000Sroot /* 3796000Sroot * Select from tty and network... 3806000Sroot */ 3816000Sroot telnet(s) 3826000Sroot int s; 3836000Sroot { 3846000Sroot register int c; 3856000Sroot int tin = fileno(stdin), tout = fileno(stdout); 3866000Sroot int on = 1; 3876000Sroot 3888378Ssam (void) mode(2); 3896000Sroot ioctl(s, FIONBIO, &on); 3906000Sroot for (;;) { 3916000Sroot int ibits = 0, obits = 0; 3926000Sroot 3936000Sroot if (nfrontp - nbackp) 3946000Sroot obits |= (1 << s); 3956000Sroot else 3966000Sroot ibits |= (1 << tin); 3976000Sroot if (tfrontp - tbackp) 3986000Sroot obits |= (1 << tout); 3996000Sroot else 4006000Sroot ibits |= (1 << s); 4016000Sroot if (scc < 0 && tcc < 0) 4026000Sroot break; 4039217Ssam select(16, &ibits, &obits, 0, 0); 4046000Sroot if (ibits == 0 && obits == 0) { 4056000Sroot sleep(5); 4066000Sroot continue; 4076000Sroot } 4086000Sroot 4096000Sroot /* 4106000Sroot * Something to read from the network... 4116000Sroot */ 4126000Sroot if (ibits & (1 << s)) { 4138378Ssam scc = read(s, sibuf, sizeof (sibuf)); 4146000Sroot if (scc < 0 && errno == EWOULDBLOCK) 4156000Sroot scc = 0; 4166000Sroot else { 4176000Sroot if (scc <= 0) 4186000Sroot break; 4196000Sroot sbp = sibuf; 4206000Sroot } 4216000Sroot } 4226000Sroot 4236000Sroot /* 4246000Sroot * Something to read from the tty... 4256000Sroot */ 4266000Sroot if (ibits & (1 << tin)) { 4278378Ssam tcc = read(tin, tibuf, sizeof (tibuf)); 4286000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 4296000Sroot tcc = 0; 4306000Sroot else { 4316000Sroot if (tcc <= 0) 4326000Sroot break; 4336000Sroot tbp = tibuf; 4346000Sroot } 4356000Sroot } 4366000Sroot 4376000Sroot while (tcc > 0) { 4386000Sroot register int c; 4396000Sroot 4406000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 4416000Sroot break; 4426000Sroot c = *tbp++ & 0377, tcc--; 4436000Sroot if (strip(c) == escape) { 4446000Sroot command(0); 4456000Sroot tcc = 0; 4466000Sroot break; 4476000Sroot } 44811758Ssam if (c == IAC) 44911758Ssam *nfrontp++ = c; 4506000Sroot *nfrontp++ = c; 4516000Sroot } 4526000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 4536000Sroot netflush(s); 4546000Sroot if (scc > 0) 4556000Sroot telrcv(); 4566000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4576000Sroot ttyflush(tout); 4586000Sroot } 4598378Ssam (void) mode(0); 4606000Sroot } 4616000Sroot 4626000Sroot command(top) 4636000Sroot int top; 4646000Sroot { 4656000Sroot register struct cmd *c; 4666000Sroot int oldmode, wasopen; 4676000Sroot 4686000Sroot oldmode = mode(0); 4696000Sroot if (!top) 4706000Sroot putchar('\n'); 4716000Sroot else 47212989Ssam signal(SIGINT, SIG_DFL); 4736000Sroot for (;;) { 4746000Sroot printf("%s> ", prompt); 47513997Ssam if (gets(line) == 0) { 47613997Ssam if (feof(stdin)) { 47713997Ssam clearerr(stdin); 47813997Ssam putchar('\n'); 47913997Ssam } 4806000Sroot break; 48113997Ssam } 4826000Sroot if (line[0] == 0) 4836000Sroot break; 4846000Sroot makeargv(); 4856000Sroot c = getcmd(margv[0]); 4866000Sroot if (c == (struct cmd *)-1) { 4876000Sroot printf("?Ambiguous command\n"); 4886000Sroot continue; 4896000Sroot } 4906000Sroot if (c == 0) { 4916000Sroot printf("?Invalid command\n"); 4926000Sroot continue; 4936000Sroot } 4946000Sroot (*c->handler)(margc, margv); 4956000Sroot if (c->handler != help) 4966000Sroot break; 4976000Sroot } 4986000Sroot if (!top) { 4996000Sroot if (!connected) 5006000Sroot longjmp(toplevel, 1); 5018378Ssam (void) mode(oldmode); 5026000Sroot } 5036000Sroot } 5046000Sroot 5056000Sroot /* 5066000Sroot * Telnet receiver states for fsm 5076000Sroot */ 5086000Sroot #define TS_DATA 0 5096000Sroot #define TS_IAC 1 5106000Sroot #define TS_WILL 2 5116000Sroot #define TS_WONT 3 5126000Sroot #define TS_DO 4 5136000Sroot #define TS_DONT 5 5146000Sroot 5156000Sroot telrcv() 5166000Sroot { 5176000Sroot register int c; 5186000Sroot static int state = TS_DATA; 5196000Sroot 5206000Sroot while (scc > 0) { 5216000Sroot c = *sbp++ & 0377, scc--; 5226000Sroot switch (state) { 5236000Sroot 5246000Sroot case TS_DATA: 5259972Ssam if (c == IAC) { 5266000Sroot state = TS_IAC; 5279972Ssam continue; 5289972Ssam } 5299972Ssam *tfrontp++ = c; 5309972Ssam /* 5319972Ssam * This hack is needed since we can't set 5329972Ssam * CRMOD on output only. Machines like MULTICS 5339972Ssam * like to send \r without \n; since we must 5349972Ssam * turn off CRMOD to get proper input, the mapping 5359972Ssam * is done here (sigh). 5369972Ssam */ 5379972Ssam if (c == '\r' && crmod) 5389972Ssam *tfrontp++ = '\n'; 5396000Sroot continue; 5406000Sroot 5416000Sroot case TS_IAC: 5426000Sroot switch (c) { 5436000Sroot 5446000Sroot case WILL: 5456000Sroot state = TS_WILL; 5466000Sroot continue; 5476000Sroot 5486000Sroot case WONT: 5496000Sroot state = TS_WONT; 5506000Sroot continue; 5516000Sroot 5526000Sroot case DO: 5536000Sroot state = TS_DO; 5546000Sroot continue; 5556000Sroot 5566000Sroot case DONT: 5576000Sroot state = TS_DONT; 5586000Sroot continue; 5596000Sroot 5606000Sroot case DM: 5616000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 5626000Sroot break; 5636000Sroot 5646000Sroot case NOP: 5656000Sroot case GA: 5666000Sroot break; 5676000Sroot 5686000Sroot default: 5696000Sroot break; 5706000Sroot } 5716000Sroot state = TS_DATA; 5726000Sroot continue; 5736000Sroot 5746000Sroot case TS_WILL: 5758345Ssam printoption("RCVD", will, c, !hisopts[c]); 5766000Sroot if (!hisopts[c]) 5776000Sroot willoption(c); 5786000Sroot state = TS_DATA; 5796000Sroot continue; 5806000Sroot 5816000Sroot case TS_WONT: 5828345Ssam printoption("RCVD", wont, c, hisopts[c]); 5836000Sroot if (hisopts[c]) 5846000Sroot wontoption(c); 5856000Sroot state = TS_DATA; 5866000Sroot continue; 5876000Sroot 5886000Sroot case TS_DO: 5898345Ssam printoption("RCVD", doopt, c, !myopts[c]); 5906000Sroot if (!myopts[c]) 5916000Sroot dooption(c); 5926000Sroot state = TS_DATA; 5936000Sroot continue; 5946000Sroot 5956000Sroot case TS_DONT: 5968345Ssam printoption("RCVD", dont, c, myopts[c]); 5976000Sroot if (myopts[c]) { 5986000Sroot myopts[c] = 0; 5996000Sroot sprintf(nfrontp, wont, c); 6008378Ssam nfrontp += sizeof (wont) - 2; 6018345Ssam printoption("SENT", wont, c); 6026000Sroot } 6036000Sroot state = TS_DATA; 6046000Sroot continue; 6056000Sroot } 6066000Sroot } 6076000Sroot } 6086000Sroot 6096000Sroot willoption(option) 6106000Sroot int option; 6116000Sroot { 6126000Sroot char *fmt; 6136000Sroot 6146000Sroot switch (option) { 6156000Sroot 6166000Sroot case TELOPT_ECHO: 6178378Ssam (void) mode(1); 6186000Sroot 6196000Sroot case TELOPT_SGA: 6206000Sroot hisopts[option] = 1; 6216000Sroot fmt = doopt; 6226000Sroot break; 6236000Sroot 6246000Sroot case TELOPT_TM: 6256000Sroot fmt = dont; 6266000Sroot break; 6276000Sroot 6286000Sroot default: 6296000Sroot fmt = dont; 6306000Sroot break; 6316000Sroot } 6326024Ssam sprintf(nfrontp, fmt, option); 6338378Ssam nfrontp += sizeof (dont) - 2; 6348345Ssam printoption("SENT", fmt, option); 6356000Sroot } 6366000Sroot 6376000Sroot wontoption(option) 6386000Sroot int option; 6396000Sroot { 6406000Sroot char *fmt; 6416000Sroot 6426000Sroot switch (option) { 6436000Sroot 6446000Sroot case TELOPT_ECHO: 6458378Ssam (void) mode(2); 6466000Sroot 6476000Sroot case TELOPT_SGA: 6486000Sroot hisopts[option] = 0; 6496000Sroot fmt = dont; 6506000Sroot break; 6516000Sroot 6526000Sroot default: 6536000Sroot fmt = dont; 6546000Sroot } 6556000Sroot sprintf(nfrontp, fmt, option); 6568378Ssam nfrontp += sizeof (doopt) - 2; 6578345Ssam printoption("SENT", fmt, option); 6586000Sroot } 6596000Sroot 6606000Sroot dooption(option) 6616000Sroot int option; 6626000Sroot { 6636000Sroot char *fmt; 6646000Sroot 6656000Sroot switch (option) { 6666000Sroot 6676000Sroot case TELOPT_TM: 6686000Sroot fmt = wont; 6696000Sroot break; 6706000Sroot 67113231Ssam case TELOPT_ECHO: 67213231Ssam (void) mode(2); 67313231Ssam fmt = will; 67413231Ssam hisopts[option] = 0; 67513231Ssam break; 67613231Ssam 6776000Sroot case TELOPT_SGA: 6786000Sroot fmt = will; 6796000Sroot break; 6806000Sroot 6816000Sroot default: 6826000Sroot fmt = wont; 6836000Sroot break; 6846000Sroot } 6856000Sroot sprintf(nfrontp, fmt, option); 6868378Ssam nfrontp += sizeof (doopt) - 2; 6878345Ssam printoption("SENT", fmt, option); 6886000Sroot } 6896000Sroot 6906000Sroot /* 6916000Sroot * Set the escape character. 6926000Sroot */ 6936000Sroot setescape(argc, argv) 6946000Sroot int argc; 6956000Sroot char *argv[]; 6966000Sroot { 6976000Sroot register char *arg; 6986000Sroot char buf[50]; 6996000Sroot 7006000Sroot if (argc > 2) 7016000Sroot arg = argv[1]; 7026000Sroot else { 7036000Sroot printf("new escape character: "); 7046000Sroot gets(buf); 7056000Sroot arg = buf; 7066000Sroot } 7076000Sroot if (arg[0] != '\0') 7086000Sroot escape = arg[0]; 7096000Sroot printf("Escape character is '%s'.\n", control(escape)); 7109972Ssam fflush(stdout); 7116000Sroot } 7126000Sroot 7136024Ssam /*VARARGS*/ 7146024Ssam setoptions() 7156024Ssam { 7169972Ssam 7176024Ssam showoptions = !showoptions; 7186024Ssam printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); 7199972Ssam fflush(stdout); 7206024Ssam } 7216024Ssam 7229972Ssam /*VARARGS*/ 7239972Ssam setcrmod() 7249972Ssam { 7259972Ssam 7269972Ssam crmod = !crmod; 7279972Ssam printf("%s map carriage return on output.\n", crmod ? "Will" : "Wont"); 7289972Ssam fflush(stdout); 7299972Ssam } 7309972Ssam 73110339Ssam /*VARARGS*/ 73210339Ssam setdebug() 73310339Ssam { 73410339Ssam 735*17484Sleres debug = debug ? 0 : 1; 73610339Ssam printf("%s turn on socket level debugging.\n", 73710339Ssam debug ? "Will" : "Wont"); 73810339Ssam fflush(stdout); 739*17484Sleres if (net > 0 && 740*17484Sleres setsockopt(net, SOL_SOCKET, SO_DEBUG, &debug, sizeof(debug)) < 0) 74111758Ssam perror("setsockopt (SO_DEBUG)"); 74210339Ssam } 74310339Ssam 7446000Sroot /* 7456000Sroot * Construct a control character sequence 7466000Sroot * for a special character. 7476000Sroot */ 7486000Sroot char * 7496000Sroot control(c) 7506000Sroot register int c; 7516000Sroot { 7526000Sroot static char buf[3]; 7536000Sroot 7546000Sroot if (c == 0177) 7556000Sroot return ("^?"); 7566000Sroot if (c >= 040) { 7576000Sroot buf[0] = c; 7586000Sroot buf[1] = 0; 7596000Sroot } else { 7606000Sroot buf[0] = '^'; 7616000Sroot buf[1] = '@'+c; 7626000Sroot buf[2] = 0; 7636000Sroot } 7646000Sroot return (buf); 7656000Sroot } 7666000Sroot 7676000Sroot struct cmd * 7686000Sroot getcmd(name) 7696000Sroot register char *name; 7706000Sroot { 7716000Sroot register char *p, *q; 7726000Sroot register struct cmd *c, *found; 7736000Sroot register int nmatches, longest; 7746000Sroot 7756000Sroot longest = 0; 7766000Sroot nmatches = 0; 7776000Sroot found = 0; 7786000Sroot for (c = cmdtab; p = c->name; c++) { 7796000Sroot for (q = name; *q == *p++; q++) 7806000Sroot if (*q == 0) /* exact match? */ 7816000Sroot return (c); 7826000Sroot if (!*q) { /* the name was a prefix */ 7836000Sroot if (q - name > longest) { 7846000Sroot longest = q - name; 7856000Sroot nmatches = 1; 7866000Sroot found = c; 7876000Sroot } else if (q - name == longest) 7886000Sroot nmatches++; 7896000Sroot } 7906000Sroot } 7916000Sroot if (nmatches > 1) 7926000Sroot return ((struct cmd *)-1); 7936000Sroot return (found); 7946000Sroot } 7956000Sroot 7966000Sroot deadpeer() 7976000Sroot { 7988378Ssam (void) mode(0); 7996000Sroot longjmp(peerdied, -1); 8006000Sroot } 8016000Sroot 8026000Sroot intr() 8036000Sroot { 8048378Ssam (void) mode(0); 8056000Sroot longjmp(toplevel, -1); 8066000Sroot } 8076000Sroot 8086000Sroot ttyflush(fd) 8096000Sroot { 8106000Sroot int n; 8116000Sroot 8126000Sroot if ((n = tfrontp - tbackp) > 0) 8136000Sroot n = write(fd, tbackp, n); 8148345Ssam if (n < 0) 8158345Ssam return; 8166000Sroot tbackp += n; 8176000Sroot if (tbackp == tfrontp) 8186000Sroot tbackp = tfrontp = ttyobuf; 8196000Sroot } 8206000Sroot 8216000Sroot netflush(fd) 8226000Sroot { 8236000Sroot int n; 8246000Sroot 8256000Sroot if ((n = nfrontp - nbackp) > 0) 8266000Sroot n = write(fd, nbackp, n); 8276501Ssam if (n < 0) { 8286501Ssam if (errno != ENOBUFS && errno != EWOULDBLOCK) { 8298378Ssam (void) mode(0); 8308377Ssam perror(hostname); 8316501Ssam close(fd); 8326501Ssam longjmp(peerdied, -1); 8336501Ssam /*NOTREACHED*/ 8346501Ssam } 8356000Sroot n = 0; 8366501Ssam } 8376000Sroot nbackp += n; 8386000Sroot if (nbackp == nfrontp) 8396000Sroot nbackp = nfrontp = netobuf; 8406000Sroot } 8416024Ssam 8426293Sroot /*VARARGS*/ 8436293Sroot printoption(direction, fmt, option, what) 8446024Ssam char *direction, *fmt; 8456293Sroot int option, what; 8466024Ssam { 8478345Ssam if (!showoptions) 8488345Ssam return; 8496024Ssam printf("%s ", direction); 8506024Ssam if (fmt == doopt) 8516024Ssam fmt = "do"; 8526024Ssam else if (fmt == dont) 8536024Ssam fmt = "dont"; 8546024Ssam else if (fmt == will) 8556024Ssam fmt = "will"; 8566024Ssam else if (fmt == wont) 8576024Ssam fmt = "wont"; 8586024Ssam else 8596024Ssam fmt = "???"; 8606024Ssam if (option < TELOPT_SUPDUP) 8616293Sroot printf("%s %s", fmt, telopts[option]); 8626024Ssam else 8636293Sroot printf("%s %d", fmt, option); 8646293Sroot if (*direction == '<') { 8656293Sroot printf("\r\n"); 8666293Sroot return; 8676293Sroot } 8686293Sroot printf(" (%s)\r\n", what ? "reply" : "don't reply"); 8696024Ssam } 870