111758Ssam #ifndef lint 2*12212Ssam static char sccsid[] = "@(#)telnet.c 4.19 (Berkeley) 05/03/83"; 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 14*12212Ssam #define TELOPTS 15*12212Ssam #include <arpa/telnet.h> 16*12212Ssam 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 999972Ssam struct ttychars otc; 1009972Ssam int oflags; 1018378Ssam 1026000Sroot main(argc, argv) 1036000Sroot int argc; 1046000Sroot char *argv[]; 1056000Sroot { 1068345Ssam sp = getservbyname("telnet", "tcp"); 1078345Ssam if (sp == 0) { 1088345Ssam fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 1098345Ssam exit(1); 1108345Ssam } 1119972Ssam ioctl(0, TIOCGET, (char *)&oflags); 1129972Ssam ioctl(0, TIOCCGET, (char *)&otc); 1136000Sroot setbuf(stdin, 0); 1146000Sroot setbuf(stdout, 0); 1156000Sroot prompt = argv[0]; 1167377Sfeldman if (argc > 1 && !strcmp(argv[1], "-d")) 1177377Sfeldman options = SO_DEBUG, argv++, argc--; 1186000Sroot if (argc != 1) { 1196000Sroot if (setjmp(toplevel) != 0) 1206000Sroot exit(0); 1216000Sroot tn(argc, argv); 1226000Sroot } 1236000Sroot setjmp(toplevel); 1246000Sroot for (;;) 1256000Sroot command(1); 1266000Sroot } 1276000Sroot 1288377Ssam char *hostname; 1298377Ssam char hnamebuf[32]; 1306000Sroot 1316000Sroot tn(argc, argv) 1326000Sroot int argc; 1336000Sroot char *argv[]; 1346000Sroot { 1356000Sroot register int c; 1368377Ssam register struct hostent *host; 1376000Sroot 1386000Sroot if (connected) { 1398377Ssam printf("?Already connected to %s\n", hostname); 1406000Sroot return; 1416000Sroot } 1426000Sroot if (argc < 2) { 1436000Sroot strcpy(line, "Connect "); 1446000Sroot printf("(to) "); 1456000Sroot gets(&line[strlen(line)]); 1466000Sroot makeargv(); 1476000Sroot argc = margc; 1486000Sroot argv = margv; 1496000Sroot } 1506000Sroot if (argc > 3) { 1516000Sroot printf("usage: %s host-name [port]\n", argv[0]); 1526000Sroot return; 1536000Sroot } 1548345Ssam host = gethostbyname(argv[1]); 1558377Ssam if (host) { 1569217Ssam sin.sin_family = host->h_addrtype; 1579217Ssam bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length); 1588377Ssam hostname = host->h_name; 1598377Ssam } else { 1609217Ssam sin.sin_family = AF_INET; 1618377Ssam sin.sin_addr.s_addr = inet_addr(argv[1]); 1628377Ssam if (sin.sin_addr.s_addr == -1) { 1638377Ssam printf("%s: unknown host\n", argv[1]); 1648377Ssam return; 1658377Ssam } 1668377Ssam strcpy(hnamebuf, argv[1]); 1678377Ssam hostname = hnamebuf; 1686000Sroot } 1698345Ssam sin.sin_port = sp->s_port; 1706024Ssam if (argc == 3) { 1716024Ssam sin.sin_port = atoi(argv[2]); 1726024Ssam if (sin.sin_port < 0) { 1736024Ssam printf("%s: bad port number\n", argv[2]); 1746024Ssam return; 1756024Ssam } 1769968Ssam sin.sin_port = htons(sin.sin_port); 1776024Ssam } 1789287Ssam net = socket(AF_INET, SOCK_STREAM, 0, 0); 1799217Ssam if (net < 0) { 1809217Ssam perror("telnet: socket"); 1816000Sroot return; 1826000Sroot } 18311758Ssam if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 18411758Ssam perror("setsockopt (SO_DEBUG)"); 1856000Sroot sigset(SIGINT, intr); 1866000Sroot sigset(SIGPIPE, deadpeer); 1876000Sroot printf("Trying...\n"); 1889217Ssam if (connect(net, (caddr_t)&sin, sizeof (sin), 0) < 0) { 1899217Ssam perror("telnet: connect"); 1906000Sroot sigset(SIGINT, SIG_DFL); 1916000Sroot return; 1926000Sroot } 1936000Sroot connected++; 1946000Sroot call(status, "status", 0); 1956000Sroot if (setjmp(peerdied) == 0) 1966000Sroot telnet(net); 1976000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 1986000Sroot exit(1); 1996000Sroot } 2006000Sroot 2016000Sroot /* 2026000Sroot * Print status about the connection. 2036000Sroot */ 2046000Sroot /*VARARGS*/ 2056000Sroot status() 2066000Sroot { 2076000Sroot if (connected) 2088377Ssam printf("Connected to %s.\n", hostname); 2096000Sroot else 2106000Sroot printf("No connection.\n"); 2116000Sroot printf("Escape character is '%s'.\n", control(escape)); 2129972Ssam fflush(stdout); 2136000Sroot } 2146000Sroot 2156000Sroot makeargv() 2166000Sroot { 2176000Sroot register char *cp; 2186000Sroot register char **argp = margv; 2196000Sroot 2206000Sroot margc = 0; 2216000Sroot for (cp = line; *cp;) { 2226000Sroot while (isspace(*cp)) 2236000Sroot cp++; 2246000Sroot if (*cp == '\0') 2256000Sroot break; 2266000Sroot *argp++ = cp; 2276000Sroot margc += 1; 2286000Sroot while (*cp != '\0' && !isspace(*cp)) 2296000Sroot cp++; 2306000Sroot if (*cp == '\0') 2316000Sroot break; 2326000Sroot *cp++ = '\0'; 2336000Sroot } 2346000Sroot *argp++ = 0; 2356000Sroot } 2366000Sroot 2376000Sroot /*VARARGS*/ 2386000Sroot suspend() 2396000Sroot { 2406000Sroot register int save; 2416000Sroot 2426000Sroot save = mode(0); 2438378Ssam kill(0, SIGTSTP); 2448378Ssam /* reget parameters in case they were changed */ 2459972Ssam ioctl(0, TIOCGET, (char *)&oflags); 2469972Ssam ioctl(0, TIOCCGET, (char *)&otc); 2478378Ssam (void) mode(save); 2486000Sroot } 2496000Sroot 2506000Sroot /*VARARGS*/ 2516000Sroot bye() 2526000Sroot { 2538378Ssam register char *op; 2546000Sroot 2558378Ssam (void) mode(0); 2566000Sroot if (connected) { 25711758Ssam shutdown(net, 2); 2586000Sroot printf("Connection closed.\n"); 2596000Sroot close(net); 2606000Sroot connected = 0; 2618378Ssam /* reset his options */ 2628378Ssam for (op = hisopts; op < &hisopts[256]; op++) 2638378Ssam *op = 0; 2646000Sroot } 2656000Sroot } 2666000Sroot 2676000Sroot /*VARARGS*/ 2686000Sroot quit() 2696000Sroot { 2706000Sroot call(bye, "bye", 0); 2716000Sroot exit(0); 2726000Sroot } 2736000Sroot 2746000Sroot /* 2756000Sroot * Help command. 2766000Sroot */ 2776000Sroot help(argc, argv) 2786000Sroot int argc; 2796000Sroot char *argv[]; 2806000Sroot { 2816000Sroot register struct cmd *c; 2826000Sroot 2836000Sroot if (argc == 1) { 2846000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 2856000Sroot for (c = cmdtab; c->name; c++) 2866000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 2876000Sroot return; 2886000Sroot } 2896000Sroot while (--argc > 0) { 2906000Sroot register char *arg; 2916000Sroot arg = *++argv; 2926000Sroot c = getcmd(arg); 2936000Sroot if (c == (struct cmd *)-1) 2946000Sroot printf("?Ambiguous help command %s\n", arg); 2956000Sroot else if (c == (struct cmd *)0) 2966000Sroot printf("?Invalid help command %s\n", arg); 2976000Sroot else 2986000Sroot printf("%s\n", c->help); 2996000Sroot } 3006000Sroot } 3016000Sroot 3026000Sroot /* 3036000Sroot * Call routine with argc, argv set from args (terminated by 0). 3046000Sroot * VARARGS2 3056000Sroot */ 3066000Sroot call(routine, args) 3076000Sroot int (*routine)(); 3086000Sroot int args; 3096000Sroot { 3106000Sroot register int *argp; 3116000Sroot register int argc; 3126000Sroot 3136000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 3146000Sroot ; 3156000Sroot (*routine)(argc, &args); 3166000Sroot } 3176000Sroot 3189972Ssam struct ttychars notc = { 3199972Ssam -1, -1, -1, -1, -1, 3209972Ssam -1, -1, -1, -1, -1, 3219972Ssam -1, -1, -1, -1 3229972Ssam }; 3239972Ssam 3246000Sroot mode(f) 3256000Sroot register int f; 3266000Sroot { 3278378Ssam static int prevmode = 0; 3289972Ssam struct ttychars *tc; 3299972Ssam int onoff, old, flags; 3306000Sroot 3318378Ssam if (prevmode == f) 3328378Ssam return (f); 3338378Ssam old = prevmode; 3348378Ssam prevmode = f; 3359972Ssam flags = oflags; 3366000Sroot switch (f) { 3378378Ssam 3386000Sroot case 0: 3396000Sroot onoff = 0; 3409972Ssam tc = &otc; 3416000Sroot break; 3426000Sroot 3436000Sroot case 1: 3446000Sroot case 2: 3459972Ssam flags |= CBREAK; 3468378Ssam if (f == 1) 3479972Ssam flags &= ~(ECHO|CRMOD); 3488378Ssam else 3499972Ssam flags |= ECHO|CRMOD; 3509972Ssam tc = ¬c; 3516000Sroot onoff = 1; 3529972Ssam break; 3539972Ssam 3549972Ssam default: 3559972Ssam return; 3566000Sroot } 3579972Ssam ioctl(fileno(stdin), TIOCCSET, (char *)tc); 3589972Ssam ioctl(fileno(stdin), TIOCSET, (char *)&flags); 3596000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 3606000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 3616000Sroot return (old); 3626000Sroot } 3636000Sroot 3646000Sroot char sibuf[BUFSIZ], *sbp; 3656000Sroot char tibuf[BUFSIZ], *tbp; 3666000Sroot int scc, tcc; 3676000Sroot 3686000Sroot /* 3696000Sroot * Select from tty and network... 3706000Sroot */ 3716000Sroot telnet(s) 3726000Sroot int s; 3736000Sroot { 3746000Sroot register int c; 3756000Sroot int tin = fileno(stdin), tout = fileno(stdout); 3766000Sroot int on = 1; 3776000Sroot 3788378Ssam (void) mode(2); 3796000Sroot ioctl(s, FIONBIO, &on); 3806000Sroot for (;;) { 3816000Sroot int ibits = 0, obits = 0; 3826000Sroot 3836000Sroot if (nfrontp - nbackp) 3846000Sroot obits |= (1 << s); 3856000Sroot else 3866000Sroot ibits |= (1 << tin); 3876000Sroot if (tfrontp - tbackp) 3886000Sroot obits |= (1 << tout); 3896000Sroot else 3906000Sroot ibits |= (1 << s); 3916000Sroot if (scc < 0 && tcc < 0) 3926000Sroot break; 3939217Ssam select(16, &ibits, &obits, 0, 0); 3946000Sroot if (ibits == 0 && obits == 0) { 3956000Sroot sleep(5); 3966000Sroot continue; 3976000Sroot } 3986000Sroot 3996000Sroot /* 4006000Sroot * Something to read from the network... 4016000Sroot */ 4026000Sroot if (ibits & (1 << s)) { 4038378Ssam scc = read(s, sibuf, sizeof (sibuf)); 4046000Sroot if (scc < 0 && errno == EWOULDBLOCK) 4056000Sroot scc = 0; 4066000Sroot else { 4076000Sroot if (scc <= 0) 4086000Sroot break; 4096000Sroot sbp = sibuf; 4106000Sroot } 4116000Sroot } 4126000Sroot 4136000Sroot /* 4146000Sroot * Something to read from the tty... 4156000Sroot */ 4166000Sroot if (ibits & (1 << tin)) { 4178378Ssam tcc = read(tin, tibuf, sizeof (tibuf)); 4186000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 4196000Sroot tcc = 0; 4206000Sroot else { 4216000Sroot if (tcc <= 0) 4226000Sroot break; 4236000Sroot tbp = tibuf; 4246000Sroot } 4256000Sroot } 4266000Sroot 4276000Sroot while (tcc > 0) { 4286000Sroot register int c; 4296000Sroot 4306000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 4316000Sroot break; 4326000Sroot c = *tbp++ & 0377, tcc--; 4336000Sroot if (strip(c) == escape) { 4346000Sroot command(0); 4356000Sroot tcc = 0; 4366000Sroot break; 4376000Sroot } 43811758Ssam if (c == IAC) 43911758Ssam *nfrontp++ = c; 4406000Sroot *nfrontp++ = c; 4416000Sroot } 4426000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 4436000Sroot netflush(s); 4446000Sroot if (scc > 0) 4456000Sroot telrcv(); 4466000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4476000Sroot ttyflush(tout); 4486000Sroot } 4498378Ssam (void) mode(0); 4506000Sroot } 4516000Sroot 4526000Sroot command(top) 4536000Sroot int top; 4546000Sroot { 4556000Sroot register struct cmd *c; 4566000Sroot int oldmode, wasopen; 4576000Sroot 4586000Sroot oldmode = mode(0); 4596000Sroot if (!top) 4606000Sroot putchar('\n'); 4616000Sroot else 4626000Sroot sigset(SIGINT, SIG_DFL); 4636000Sroot for (;;) { 4646000Sroot printf("%s> ", prompt); 4656000Sroot if (gets(line) == 0) 4666000Sroot break; 4676000Sroot if (line[0] == 0) 4686000Sroot break; 4696000Sroot makeargv(); 4706000Sroot c = getcmd(margv[0]); 4716000Sroot if (c == (struct cmd *)-1) { 4726000Sroot printf("?Ambiguous command\n"); 4736000Sroot continue; 4746000Sroot } 4756000Sroot if (c == 0) { 4766000Sroot printf("?Invalid command\n"); 4776000Sroot continue; 4786000Sroot } 4796000Sroot (*c->handler)(margc, margv); 4806000Sroot if (c->handler != help) 4816000Sroot break; 4826000Sroot } 4836000Sroot if (!top) { 4846000Sroot if (!connected) 4856000Sroot longjmp(toplevel, 1); 4868378Ssam (void) mode(oldmode); 4876000Sroot } 4886000Sroot } 4896000Sroot 4906000Sroot /* 4916000Sroot * Telnet receiver states for fsm 4926000Sroot */ 4936000Sroot #define TS_DATA 0 4946000Sroot #define TS_IAC 1 4956000Sroot #define TS_WILL 2 4966000Sroot #define TS_WONT 3 4976000Sroot #define TS_DO 4 4986000Sroot #define TS_DONT 5 4996000Sroot 5006000Sroot telrcv() 5016000Sroot { 5026000Sroot register int c; 5036000Sroot static int state = TS_DATA; 5046000Sroot 5056000Sroot while (scc > 0) { 5066000Sroot c = *sbp++ & 0377, scc--; 5076000Sroot switch (state) { 5086000Sroot 5096000Sroot case TS_DATA: 5109972Ssam if (c == IAC) { 5116000Sroot state = TS_IAC; 5129972Ssam continue; 5139972Ssam } 5149972Ssam *tfrontp++ = c; 5159972Ssam /* 5169972Ssam * This hack is needed since we can't set 5179972Ssam * CRMOD on output only. Machines like MULTICS 5189972Ssam * like to send \r without \n; since we must 5199972Ssam * turn off CRMOD to get proper input, the mapping 5209972Ssam * is done here (sigh). 5219972Ssam */ 5229972Ssam if (c == '\r' && crmod) 5239972Ssam *tfrontp++ = '\n'; 5246000Sroot continue; 5256000Sroot 5266000Sroot case TS_IAC: 5276000Sroot switch (c) { 5286000Sroot 5296000Sroot case WILL: 5306000Sroot state = TS_WILL; 5316000Sroot continue; 5326000Sroot 5336000Sroot case WONT: 5346000Sroot state = TS_WONT; 5356000Sroot continue; 5366000Sroot 5376000Sroot case DO: 5386000Sroot state = TS_DO; 5396000Sroot continue; 5406000Sroot 5416000Sroot case DONT: 5426000Sroot state = TS_DONT; 5436000Sroot continue; 5446000Sroot 5456000Sroot case DM: 5466000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 5476000Sroot break; 5486000Sroot 5496000Sroot case NOP: 5506000Sroot case GA: 5516000Sroot break; 5526000Sroot 5536000Sroot default: 5546000Sroot break; 5556000Sroot } 5566000Sroot state = TS_DATA; 5576000Sroot continue; 5586000Sroot 5596000Sroot case TS_WILL: 5608345Ssam printoption("RCVD", will, c, !hisopts[c]); 5616000Sroot if (!hisopts[c]) 5626000Sroot willoption(c); 5636000Sroot state = TS_DATA; 5646000Sroot continue; 5656000Sroot 5666000Sroot case TS_WONT: 5678345Ssam printoption("RCVD", wont, c, hisopts[c]); 5686000Sroot if (hisopts[c]) 5696000Sroot wontoption(c); 5706000Sroot state = TS_DATA; 5716000Sroot continue; 5726000Sroot 5736000Sroot case TS_DO: 5748345Ssam printoption("RCVD", doopt, c, !myopts[c]); 5756000Sroot if (!myopts[c]) 5766000Sroot dooption(c); 5776000Sroot state = TS_DATA; 5786000Sroot continue; 5796000Sroot 5806000Sroot case TS_DONT: 5818345Ssam printoption("RCVD", dont, c, myopts[c]); 5826000Sroot if (myopts[c]) { 5836000Sroot myopts[c] = 0; 5846000Sroot sprintf(nfrontp, wont, c); 5858378Ssam nfrontp += sizeof (wont) - 2; 5868345Ssam printoption("SENT", wont, c); 5876000Sroot } 5886000Sroot state = TS_DATA; 5896000Sroot continue; 5906000Sroot } 5916000Sroot } 5926000Sroot } 5936000Sroot 5946000Sroot willoption(option) 5956000Sroot int option; 5966000Sroot { 5976000Sroot char *fmt; 5986000Sroot 5996000Sroot switch (option) { 6006000Sroot 6016000Sroot case TELOPT_ECHO: 6028378Ssam (void) mode(1); 6036000Sroot 6046000Sroot case TELOPT_SGA: 6056000Sroot hisopts[option] = 1; 6066000Sroot fmt = doopt; 6076000Sroot break; 6086000Sroot 6096000Sroot case TELOPT_TM: 6106000Sroot fmt = dont; 6116000Sroot break; 6126000Sroot 6136000Sroot default: 6146000Sroot fmt = dont; 6156000Sroot break; 6166000Sroot } 6176024Ssam sprintf(nfrontp, fmt, option); 6188378Ssam nfrontp += sizeof (dont) - 2; 6198345Ssam printoption("SENT", fmt, option); 6206000Sroot } 6216000Sroot 6226000Sroot wontoption(option) 6236000Sroot int option; 6246000Sroot { 6256000Sroot char *fmt; 6266000Sroot 6276000Sroot switch (option) { 6286000Sroot 6296000Sroot case TELOPT_ECHO: 6308378Ssam (void) mode(2); 6316000Sroot 6326000Sroot case TELOPT_SGA: 6336000Sroot hisopts[option] = 0; 6346000Sroot fmt = dont; 6356000Sroot break; 6366000Sroot 6376000Sroot default: 6386000Sroot fmt = dont; 6396000Sroot } 6406000Sroot sprintf(nfrontp, fmt, option); 6418378Ssam nfrontp += sizeof (doopt) - 2; 6428345Ssam printoption("SENT", fmt, option); 6436000Sroot } 6446000Sroot 6456000Sroot dooption(option) 6466000Sroot int option; 6476000Sroot { 6486000Sroot char *fmt; 6496000Sroot 6506000Sroot switch (option) { 6516000Sroot 6526000Sroot case TELOPT_TM: 6536000Sroot fmt = wont; 6546000Sroot break; 6556000Sroot 6566000Sroot case TELOPT_SGA: 6576000Sroot fmt = will; 6586000Sroot break; 6596000Sroot 6606000Sroot default: 6616000Sroot fmt = wont; 6626000Sroot break; 6636000Sroot } 6646000Sroot sprintf(nfrontp, fmt, option); 6658378Ssam nfrontp += sizeof (doopt) - 2; 6668345Ssam printoption("SENT", fmt, option); 6676000Sroot } 6686000Sroot 6696000Sroot /* 6706000Sroot * Set the escape character. 6716000Sroot */ 6726000Sroot setescape(argc, argv) 6736000Sroot int argc; 6746000Sroot char *argv[]; 6756000Sroot { 6766000Sroot register char *arg; 6776000Sroot char buf[50]; 6786000Sroot 6796000Sroot if (argc > 2) 6806000Sroot arg = argv[1]; 6816000Sroot else { 6826000Sroot printf("new escape character: "); 6836000Sroot gets(buf); 6846000Sroot arg = buf; 6856000Sroot } 6866000Sroot if (arg[0] != '\0') 6876000Sroot escape = arg[0]; 6886000Sroot printf("Escape character is '%s'.\n", control(escape)); 6899972Ssam fflush(stdout); 6906000Sroot } 6916000Sroot 6926024Ssam /*VARARGS*/ 6936024Ssam setoptions() 6946024Ssam { 6959972Ssam 6966024Ssam showoptions = !showoptions; 6976024Ssam printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); 6989972Ssam fflush(stdout); 6996024Ssam } 7006024Ssam 7019972Ssam /*VARARGS*/ 7029972Ssam setcrmod() 7039972Ssam { 7049972Ssam 7059972Ssam crmod = !crmod; 7069972Ssam printf("%s map carriage return on output.\n", crmod ? "Will" : "Wont"); 7079972Ssam fflush(stdout); 7089972Ssam } 7099972Ssam 71010339Ssam /*VARARGS*/ 71110339Ssam setdebug() 71210339Ssam { 71310339Ssam 71410339Ssam debug = !debug; 71510339Ssam printf("%s turn on socket level debugging.\n", 71610339Ssam debug ? "Will" : "Wont"); 71710339Ssam fflush(stdout); 71811758Ssam if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 71911758Ssam perror("setsockopt (SO_DEBUG)"); 72010339Ssam } 72110339Ssam 7226000Sroot /* 7236000Sroot * Construct a control character sequence 7246000Sroot * for a special character. 7256000Sroot */ 7266000Sroot char * 7276000Sroot control(c) 7286000Sroot register int c; 7296000Sroot { 7306000Sroot static char buf[3]; 7316000Sroot 7326000Sroot if (c == 0177) 7336000Sroot return ("^?"); 7346000Sroot if (c >= 040) { 7356000Sroot buf[0] = c; 7366000Sroot buf[1] = 0; 7376000Sroot } else { 7386000Sroot buf[0] = '^'; 7396000Sroot buf[1] = '@'+c; 7406000Sroot buf[2] = 0; 7416000Sroot } 7426000Sroot return (buf); 7436000Sroot } 7446000Sroot 7456000Sroot struct cmd * 7466000Sroot getcmd(name) 7476000Sroot register char *name; 7486000Sroot { 7496000Sroot register char *p, *q; 7506000Sroot register struct cmd *c, *found; 7516000Sroot register int nmatches, longest; 7526000Sroot 7536000Sroot longest = 0; 7546000Sroot nmatches = 0; 7556000Sroot found = 0; 7566000Sroot for (c = cmdtab; p = c->name; c++) { 7576000Sroot for (q = name; *q == *p++; q++) 7586000Sroot if (*q == 0) /* exact match? */ 7596000Sroot return (c); 7606000Sroot if (!*q) { /* the name was a prefix */ 7616000Sroot if (q - name > longest) { 7626000Sroot longest = q - name; 7636000Sroot nmatches = 1; 7646000Sroot found = c; 7656000Sroot } else if (q - name == longest) 7666000Sroot nmatches++; 7676000Sroot } 7686000Sroot } 7696000Sroot if (nmatches > 1) 7706000Sroot return ((struct cmd *)-1); 7716000Sroot return (found); 7726000Sroot } 7736000Sroot 7746000Sroot deadpeer() 7756000Sroot { 7766000Sroot sigset(SIGPIPE, deadpeer); 7778378Ssam (void) mode(0); 7786000Sroot longjmp(peerdied, -1); 7796000Sroot } 7806000Sroot 7816000Sroot intr() 7826000Sroot { 7836000Sroot sigset(SIGINT, intr); 7848378Ssam (void) mode(0); 7856000Sroot longjmp(toplevel, -1); 7866000Sroot } 7876000Sroot 7886000Sroot ttyflush(fd) 7896000Sroot { 7906000Sroot int n; 7916000Sroot 7926000Sroot if ((n = tfrontp - tbackp) > 0) 7936000Sroot n = write(fd, tbackp, n); 7948345Ssam if (n < 0) 7958345Ssam return; 7966000Sroot tbackp += n; 7976000Sroot if (tbackp == tfrontp) 7986000Sroot tbackp = tfrontp = ttyobuf; 7996000Sroot } 8006000Sroot 8016000Sroot netflush(fd) 8026000Sroot { 8036000Sroot int n; 8046000Sroot 8056000Sroot if ((n = nfrontp - nbackp) > 0) 8066000Sroot n = write(fd, nbackp, n); 8076501Ssam if (n < 0) { 8086501Ssam if (errno != ENOBUFS && errno != EWOULDBLOCK) { 8098378Ssam (void) mode(0); 8108377Ssam perror(hostname); 8116501Ssam close(fd); 8126501Ssam longjmp(peerdied, -1); 8136501Ssam /*NOTREACHED*/ 8146501Ssam } 8156000Sroot n = 0; 8166501Ssam } 8176000Sroot nbackp += n; 8186000Sroot if (nbackp == nfrontp) 8196000Sroot nbackp = nfrontp = netobuf; 8206000Sroot } 8216024Ssam 8226293Sroot /*VARARGS*/ 8236293Sroot printoption(direction, fmt, option, what) 8246024Ssam char *direction, *fmt; 8256293Sroot int option, what; 8266024Ssam { 8278345Ssam if (!showoptions) 8288345Ssam return; 8296024Ssam printf("%s ", direction); 8306024Ssam if (fmt == doopt) 8316024Ssam fmt = "do"; 8326024Ssam else if (fmt == dont) 8336024Ssam fmt = "dont"; 8346024Ssam else if (fmt == will) 8356024Ssam fmt = "will"; 8366024Ssam else if (fmt == wont) 8376024Ssam fmt = "wont"; 8386024Ssam else 8396024Ssam fmt = "???"; 8406024Ssam if (option < TELOPT_SUPDUP) 8416293Sroot printf("%s %s", fmt, telopts[option]); 8426024Ssam else 8436293Sroot printf("%s %d", fmt, option); 8446293Sroot if (*direction == '<') { 8456293Sroot printf("\r\n"); 8466293Sroot return; 8476293Sroot } 8486293Sroot printf(" (%s)\r\n", what ? "reply" : "don't reply"); 8496024Ssam } 850