xref: /csrg-svn/usr.bin/telnet/telnet.c (revision 6000)
1*6000Sroot /*	telnet.c	4.1	82/02/28	*/
2*6000Sroot 
3*6000Sroot /*
4*6000Sroot  * User telnet program.
5*6000Sroot  */
6*6000Sroot #include <stdio.h>
7*6000Sroot #include <ctype.h>
8*6000Sroot #include <errno.h>
9*6000Sroot #include <signal.h>
10*6000Sroot #include <sgtty.h>
11*6000Sroot #include <setjmp.h>
12*6000Sroot #include <sys/types.h>
13*6000Sroot #include <sys/socket.h>
14*6000Sroot #include <net/in.h>
15*6000Sroot #include "telnet.h"
16*6000Sroot 
17*6000Sroot #define	ctrl(x)		((x) & 037)
18*6000Sroot #define	strip(x)	((x)&0177)
19*6000Sroot #define	INFINITY	10000000
20*6000Sroot #define	swab(x)		((((x) >> 8) | ((x) << 8)) & 0xffff)
21*6000Sroot 
22*6000Sroot char	ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf;
23*6000Sroot char	netobuf[BUFSIZ] =
24*6000Sroot 	{ IAC, DO, TELOPT_ECHO, IAC, DO, TELOPT_SGA,
25*6000Sroot 	  IAC, WONT, TELOPT_SGA },
26*6000Sroot 	*nfrontp = netobuf + 9, *nbackp = netobuf;
27*6000Sroot 
28*6000Sroot char	hisopts[256];
29*6000Sroot char	myopts[256];
30*6000Sroot 
31*6000Sroot char	doopt[] = { IAC, DO, '%', 'c', 0 };
32*6000Sroot char	dont[] = { IAC, DONT, '%', 'c', 0 };
33*6000Sroot char	will[] = { IAC, WILL, '%', 'c', 0 };
34*6000Sroot char	wont[] = { IAC, WONT, '%', 'c', 0 };
35*6000Sroot 
36*6000Sroot int	connected;
37*6000Sroot int	net;
38*6000Sroot char	*prompt;
39*6000Sroot char	escape = ctrl('_');
40*6000Sroot 
41*6000Sroot char	line[200];
42*6000Sroot int	margc;
43*6000Sroot char	*margv[20];
44*6000Sroot 
45*6000Sroot jmp_buf	toplevel;
46*6000Sroot jmp_buf	peerdied;
47*6000Sroot 
48*6000Sroot extern	int errno;
49*6000Sroot 
50*6000Sroot int	tn(), quit(), suspend(), bye(), help();
51*6000Sroot int	setescape(), status(), toggle();
52*6000Sroot 
53*6000Sroot #define HELPINDENT (sizeof("connect"))
54*6000Sroot 
55*6000Sroot struct cmd {
56*6000Sroot 	char	*name;
57*6000Sroot 	char	*help;
58*6000Sroot 	int	(*handler)();
59*6000Sroot };
60*6000Sroot 
61*6000Sroot char	ohelp[] = "connect to a site";
62*6000Sroot char	chelp[] = "close current connection";
63*6000Sroot char	qhelp[] = "exit telnet";
64*6000Sroot char	zhelp[] = "suspend telnet";
65*6000Sroot char	ehelp[] = "set escape character";
66*6000Sroot char	shelp[] = "print status information";
67*6000Sroot char	hhelp[] = "print help information";
68*6000Sroot 
69*6000Sroot struct cmd cmdtab[] = {
70*6000Sroot 	{ "open",	ohelp,		tn },
71*6000Sroot 	{ "close",	chelp,		bye },
72*6000Sroot 	{ "quit",	qhelp,		quit },
73*6000Sroot 	{ "z",		zhelp,		suspend },
74*6000Sroot 	{ "escape",	ehelp,		setescape },
75*6000Sroot 	{ "status",	shelp,		status },
76*6000Sroot 	{ "?",		hhelp,		help },
77*6000Sroot 	0
78*6000Sroot };
79*6000Sroot 
80*6000Sroot struct	sockaddr_in sin = { AF_INET, swab(IPPORT_TELNET) };
81*6000Sroot 
82*6000Sroot int	intr(), deadpeer();
83*6000Sroot char	*control();
84*6000Sroot struct	cmd *getcmd();
85*6000Sroot 
86*6000Sroot main(argc, argv)
87*6000Sroot 	int argc;
88*6000Sroot 	char *argv[];
89*6000Sroot {
90*6000Sroot 	setbuf(stdin, 0);
91*6000Sroot 	setbuf(stdout, 0);
92*6000Sroot 	prompt = argv[0];
93*6000Sroot 	if (argc != 1) {
94*6000Sroot 		if (setjmp(toplevel) != 0)
95*6000Sroot 			exit(0);
96*6000Sroot 		tn(argc, argv);
97*6000Sroot 	}
98*6000Sroot 	setjmp(toplevel);
99*6000Sroot 	for (;;)
100*6000Sroot 		command(1);
101*6000Sroot }
102*6000Sroot 
103*6000Sroot char host_name[100];
104*6000Sroot 
105*6000Sroot tn(argc, argv)
106*6000Sroot 	int argc;
107*6000Sroot 	char *argv[];
108*6000Sroot {
109*6000Sroot 	register int c;
110*6000Sroot 
111*6000Sroot 	if (connected) {
112*6000Sroot 		printf("?Already connected to %s\n", host_name);
113*6000Sroot 		return;
114*6000Sroot 	}
115*6000Sroot 	if (argc < 2) {
116*6000Sroot 		strcpy(line, "Connect ");
117*6000Sroot 		printf("(to) ");
118*6000Sroot 		gets(&line[strlen(line)]);
119*6000Sroot 		makeargv();
120*6000Sroot 		argc = margc;
121*6000Sroot 		argv = margv;
122*6000Sroot 	}
123*6000Sroot 	if (argc > 3) {
124*6000Sroot 		printf("usage: %s host-name [port]\n", argv[0]);
125*6000Sroot 		return;
126*6000Sroot 	}
127*6000Sroot 	sin.sin_addr.s_addr = rhost(&argv[1]);
128*6000Sroot 	if (sin.sin_addr.s_addr == 0) {
129*6000Sroot 		printf("%s: unknown host\n", argv[1]);
130*6000Sroot 		return;
131*6000Sroot 	}
132*6000Sroot 	if ((net = socket(SOCK_STREAM, 0, 0, 0)) < 0) {
133*6000Sroot 		perror("socket");
134*6000Sroot 		return;
135*6000Sroot 	}
136*6000Sroot 	if (argc == 3)
137*6000Sroot 		sin.sin_port = atoi(argv[2]);
138*6000Sroot 	sigset(SIGINT, intr);
139*6000Sroot 	sigset(SIGPIPE, deadpeer);
140*6000Sroot 	printf("Trying...\n");
141*6000Sroot 	if (connect(net, &sin)) {
142*6000Sroot 		perror("connect");
143*6000Sroot 		sigset(SIGINT, SIG_DFL);
144*6000Sroot 		return;
145*6000Sroot 	}
146*6000Sroot 	strcpy(host_name, argv[1]);
147*6000Sroot 	connected++;
148*6000Sroot 	call(status, "status", 0);
149*6000Sroot 	if (setjmp(peerdied) == 0)
150*6000Sroot 		telnet(net);
151*6000Sroot 	fprintf(stderr, "Connection closed by foreign host.\n");
152*6000Sroot 	exit(1);
153*6000Sroot }
154*6000Sroot 
155*6000Sroot /*
156*6000Sroot  * Print status about the connection.
157*6000Sroot  */
158*6000Sroot /*VARARGS*/
159*6000Sroot status()
160*6000Sroot {
161*6000Sroot 	if (connected)
162*6000Sroot 		printf("Connected to %s.\n", host_name);
163*6000Sroot 	else
164*6000Sroot 		printf("No connection.\n");
165*6000Sroot 	printf("Escape character is '%s'.\n", control(escape));
166*6000Sroot }
167*6000Sroot 
168*6000Sroot makeargv()
169*6000Sroot {
170*6000Sroot 	register char *cp;
171*6000Sroot 	register char **argp = margv;
172*6000Sroot 
173*6000Sroot 	margc = 0;
174*6000Sroot 	for (cp = line; *cp;) {
175*6000Sroot 		while (isspace(*cp))
176*6000Sroot 			cp++;
177*6000Sroot 		if (*cp == '\0')
178*6000Sroot 			break;
179*6000Sroot 		*argp++ = cp;
180*6000Sroot 		margc += 1;
181*6000Sroot 		while (*cp != '\0' && !isspace(*cp))
182*6000Sroot 			cp++;
183*6000Sroot 		if (*cp == '\0')
184*6000Sroot 			break;
185*6000Sroot 		*cp++ = '\0';
186*6000Sroot 	}
187*6000Sroot 	*argp++ = 0;
188*6000Sroot }
189*6000Sroot 
190*6000Sroot /*VARARGS*/
191*6000Sroot suspend()
192*6000Sroot {
193*6000Sroot 	register int save;
194*6000Sroot 
195*6000Sroot 	save = mode(0);
196*6000Sroot 	kill(0, SIGTSTP);	/* get whole process group */
197*6000Sroot 	mode(save);
198*6000Sroot }
199*6000Sroot 
200*6000Sroot /*VARARGS*/
201*6000Sroot bye()
202*6000Sroot {
203*6000Sroot 	int how = 2;
204*6000Sroot 
205*6000Sroot 	mode(0);
206*6000Sroot 	if (connected) {
207*6000Sroot 		ioctl(net, SIOCDONE, &how);
208*6000Sroot 		printf("Connection closed.\n");
209*6000Sroot 		close(net);
210*6000Sroot 		connected = 0;
211*6000Sroot 	}
212*6000Sroot }
213*6000Sroot 
214*6000Sroot /*VARARGS*/
215*6000Sroot quit()
216*6000Sroot {
217*6000Sroot 	call(bye, "bye", 0);
218*6000Sroot 	exit(0);
219*6000Sroot }
220*6000Sroot 
221*6000Sroot /*
222*6000Sroot  * Help command.
223*6000Sroot  * Call each command handler with argc == 0 and argv[0] == name.
224*6000Sroot  */
225*6000Sroot help(argc, argv)
226*6000Sroot 	int argc;
227*6000Sroot 	char *argv[];
228*6000Sroot {
229*6000Sroot 	register struct cmd *c;
230*6000Sroot 
231*6000Sroot 	if (argc == 1) {
232*6000Sroot 		printf("Commands may be abbreviated.  Commands are:\n\n");
233*6000Sroot 		for (c = cmdtab; c->name; c++)
234*6000Sroot 			printf("%-*s\t%s\n", HELPINDENT, c->name, c->help);
235*6000Sroot 		return;
236*6000Sroot 	}
237*6000Sroot 	while (--argc > 0) {
238*6000Sroot 		register char *arg;
239*6000Sroot 		arg = *++argv;
240*6000Sroot 		c = getcmd(arg);
241*6000Sroot 		if (c == (struct cmd *)-1)
242*6000Sroot 			printf("?Ambiguous help command %s\n", arg);
243*6000Sroot 		else if (c == (struct cmd *)0)
244*6000Sroot 			printf("?Invalid help command %s\n", arg);
245*6000Sroot 		else
246*6000Sroot 			printf("%s\n", c->help);
247*6000Sroot 	}
248*6000Sroot }
249*6000Sroot 
250*6000Sroot /*
251*6000Sroot  * Call routine with argc, argv set from args (terminated by 0).
252*6000Sroot  * VARARGS2
253*6000Sroot  */
254*6000Sroot call(routine, args)
255*6000Sroot 	int (*routine)();
256*6000Sroot 	int args;
257*6000Sroot {
258*6000Sroot 	register int *argp;
259*6000Sroot 	register int argc;
260*6000Sroot 
261*6000Sroot 	for (argc = 0, argp = &args; *argp++ != 0; argc++)
262*6000Sroot 		;
263*6000Sroot 	(*routine)(argc, &args);
264*6000Sroot }
265*6000Sroot 
266*6000Sroot mode(f)
267*6000Sroot 	register int f;
268*6000Sroot {
269*6000Sroot 	register int old;
270*6000Sroot 	struct sgttyb stbuf;
271*6000Sroot 	static int ttymode = 0;
272*6000Sroot 	int onoff;
273*6000Sroot 
274*6000Sroot 	ioctl(fileno(stdin), TIOCGETP, &stbuf);
275*6000Sroot 	old = ttymode;
276*6000Sroot 	ttymode = f;
277*6000Sroot 	switch (f) {
278*6000Sroot 	case 0:
279*6000Sroot 		stbuf.sg_flags &= ~RAW;
280*6000Sroot 		stbuf.sg_flags |= ECHO|CRMOD;
281*6000Sroot 		onoff = 0;
282*6000Sroot 		break;
283*6000Sroot 
284*6000Sroot 	case 1:
285*6000Sroot 		stbuf.sg_flags |= RAW;
286*6000Sroot 		stbuf.sg_flags &= ~(ECHO|CRMOD);
287*6000Sroot 		onoff = 1;
288*6000Sroot 		break;
289*6000Sroot 
290*6000Sroot 	case 2:
291*6000Sroot 		stbuf.sg_flags |= RAW;
292*6000Sroot 		stbuf.sg_flags |= ECHO|CRMOD;
293*6000Sroot 		onoff = 1;
294*6000Sroot 	}
295*6000Sroot 	ioctl(fileno(stdin), TIOCSETN, &stbuf);
296*6000Sroot 	ioctl(fileno(stdin), FIONBIO, &onoff);
297*6000Sroot 	ioctl(fileno(stdout), FIONBIO, &onoff);
298*6000Sroot 	return (old);
299*6000Sroot }
300*6000Sroot 
301*6000Sroot char	sibuf[BUFSIZ], *sbp;
302*6000Sroot char	tibuf[BUFSIZ], *tbp;
303*6000Sroot int	scc, tcc;
304*6000Sroot 
305*6000Sroot /*
306*6000Sroot  * Select from tty and network...
307*6000Sroot  */
308*6000Sroot telnet(s)
309*6000Sroot 	int s;
310*6000Sroot {
311*6000Sroot 	register int c;
312*6000Sroot 	int tin = fileno(stdin), tout = fileno(stdout);
313*6000Sroot 	int on = 1;
314*6000Sroot 
315*6000Sroot 	mode(1);
316*6000Sroot 	sprintf(nfrontp, doopt, TELOPT_ECHO);
317*6000Sroot 	nfrontp += sizeof(doopt) - 2;
318*6000Sroot 	sprintf(nfrontp, doopt, TELOPT_SGA);
319*6000Sroot 	nfrontp += sizeof(doopt) - 2;
320*6000Sroot 	sprintf(nfrontp, will, TELOPT_SGA);
321*6000Sroot 	nfrontp += sizeof(doopt) - 2;
322*6000Sroot 	ioctl(s, FIONBIO, &on);
323*6000Sroot 	for (;;) {
324*6000Sroot 		int ibits = 0, obits = 0;
325*6000Sroot 
326*6000Sroot 		if (nfrontp - nbackp)
327*6000Sroot 			obits |= (1 << s);
328*6000Sroot 		else
329*6000Sroot 			ibits |= (1 << tin);
330*6000Sroot 		if (tfrontp - tbackp)
331*6000Sroot 			obits |= (1 << tout);
332*6000Sroot 		else
333*6000Sroot 			ibits |= (1 << s);
334*6000Sroot 		if (scc < 0 && tcc < 0)
335*6000Sroot 			break;
336*6000Sroot 		select(32, &ibits, &obits, INFINITY);
337*6000Sroot 		if (ibits == 0 && obits == 0) {
338*6000Sroot 			sleep(5);
339*6000Sroot 			continue;
340*6000Sroot 		}
341*6000Sroot 
342*6000Sroot 		/*
343*6000Sroot 		 * Something to read from the network...
344*6000Sroot 		 */
345*6000Sroot 		if (ibits & (1 << s)) {
346*6000Sroot 			scc = read(s, sibuf, sizeof(sibuf));
347*6000Sroot 			if (scc < 0 && errno == EWOULDBLOCK)
348*6000Sroot 				scc = 0;
349*6000Sroot 			else {
350*6000Sroot 				if (scc <= 0)
351*6000Sroot 					break;
352*6000Sroot 				sbp = sibuf;
353*6000Sroot 			}
354*6000Sroot 		}
355*6000Sroot 
356*6000Sroot 		/*
357*6000Sroot 		 * Something to read from the tty...
358*6000Sroot 		 */
359*6000Sroot 		if (ibits & (1 << tin)) {
360*6000Sroot 			tcc = read(tin, tibuf, sizeof(tibuf));
361*6000Sroot 			if (tcc < 0 && errno == EWOULDBLOCK)
362*6000Sroot 				tcc = 0;
363*6000Sroot 			else {
364*6000Sroot 				if (tcc <= 0)
365*6000Sroot 					break;
366*6000Sroot 				tbp = tibuf;
367*6000Sroot 			}
368*6000Sroot 		}
369*6000Sroot 
370*6000Sroot 		while (tcc > 0) {
371*6000Sroot 			register int c;
372*6000Sroot 
373*6000Sroot 			if ((&netobuf[BUFSIZ] - nfrontp) < 2)
374*6000Sroot 				break;
375*6000Sroot 			c = *tbp++ & 0377, tcc--;
376*6000Sroot 			if (strip(c) == escape) {
377*6000Sroot 				command(0);
378*6000Sroot 				tcc = 0;
379*6000Sroot 				break;
380*6000Sroot 			}
381*6000Sroot 			*nfrontp++ = c;
382*6000Sroot 		}
383*6000Sroot 		if ((obits & (1 << s)) && (nfrontp - nbackp) > 0)
384*6000Sroot 			netflush(s);
385*6000Sroot 		if (scc > 0)
386*6000Sroot 			telrcv();
387*6000Sroot 		if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0)
388*6000Sroot 			ttyflush(tout);
389*6000Sroot 	}
390*6000Sroot 	mode(0);
391*6000Sroot }
392*6000Sroot 
393*6000Sroot command(top)
394*6000Sroot 	int top;
395*6000Sroot {
396*6000Sroot 	register struct cmd *c;
397*6000Sroot 	int oldmode, wasopen;
398*6000Sroot 
399*6000Sroot 	oldmode = mode(0);
400*6000Sroot 	if (!top)
401*6000Sroot 		putchar('\n');
402*6000Sroot 	else
403*6000Sroot 		sigset(SIGINT, SIG_DFL);
404*6000Sroot 	for (;;) {
405*6000Sroot 		printf("%s> ", prompt);
406*6000Sroot 		if (gets(line) == 0)
407*6000Sroot 			break;
408*6000Sroot 		if (line[0] == 0)
409*6000Sroot 			break;
410*6000Sroot 		makeargv();
411*6000Sroot 		c = getcmd(margv[0]);
412*6000Sroot 		if (c == (struct cmd *)-1) {
413*6000Sroot 			printf("?Ambiguous command\n");
414*6000Sroot 			continue;
415*6000Sroot 		}
416*6000Sroot 		if (c == 0) {
417*6000Sroot 			printf("?Invalid command\n");
418*6000Sroot 			continue;
419*6000Sroot 		}
420*6000Sroot 		(*c->handler)(margc, margv);
421*6000Sroot 		if (c->handler != help)
422*6000Sroot 			break;
423*6000Sroot 	}
424*6000Sroot 	if (!top) {
425*6000Sroot 		if (!connected)
426*6000Sroot 			longjmp(toplevel, 1);
427*6000Sroot 		mode(oldmode);
428*6000Sroot 	}
429*6000Sroot }
430*6000Sroot 
431*6000Sroot /*
432*6000Sroot  * Telnet receiver states for fsm
433*6000Sroot  */
434*6000Sroot #define	TS_DATA		0
435*6000Sroot #define	TS_IAC		1
436*6000Sroot #define	TS_WILL		2
437*6000Sroot #define	TS_WONT		3
438*6000Sroot #define	TS_DO		4
439*6000Sroot #define	TS_DONT		5
440*6000Sroot 
441*6000Sroot telrcv()
442*6000Sroot {
443*6000Sroot 	register int c;
444*6000Sroot 	static int state = TS_DATA;
445*6000Sroot 
446*6000Sroot 	while (scc > 0) {
447*6000Sroot 		c = *sbp++ & 0377, scc--;
448*6000Sroot 		switch (state) {
449*6000Sroot 
450*6000Sroot 		case TS_DATA:
451*6000Sroot 			if (c == IAC)
452*6000Sroot 				state = TS_IAC;
453*6000Sroot 			else
454*6000Sroot 				*tfrontp++ = c;
455*6000Sroot 			continue;
456*6000Sroot 
457*6000Sroot 		case TS_IAC:
458*6000Sroot 			switch (c) {
459*6000Sroot 
460*6000Sroot 			case WILL:
461*6000Sroot 				state = TS_WILL;
462*6000Sroot 				continue;
463*6000Sroot 
464*6000Sroot 			case WONT:
465*6000Sroot 				state = TS_WONT;
466*6000Sroot 				continue;
467*6000Sroot 
468*6000Sroot 			case DO:
469*6000Sroot 				state = TS_DO;
470*6000Sroot 				continue;
471*6000Sroot 
472*6000Sroot 			case DONT:
473*6000Sroot 				state = TS_DONT;
474*6000Sroot 				continue;
475*6000Sroot 
476*6000Sroot 			case DM:
477*6000Sroot 				ioctl(fileno(stdout), TIOCFLUSH, 0);
478*6000Sroot 				break;
479*6000Sroot 
480*6000Sroot 			case NOP:
481*6000Sroot 			case GA:
482*6000Sroot 				break;
483*6000Sroot 
484*6000Sroot 			default:
485*6000Sroot 				break;
486*6000Sroot 			}
487*6000Sroot 			state = TS_DATA;
488*6000Sroot 			continue;
489*6000Sroot 
490*6000Sroot 		case TS_WILL:
491*6000Sroot 			if (!hisopts[c])
492*6000Sroot 				willoption(c);
493*6000Sroot 			state = TS_DATA;
494*6000Sroot 			continue;
495*6000Sroot 
496*6000Sroot 		case TS_WONT:
497*6000Sroot 			if (hisopts[c])
498*6000Sroot 				wontoption(c);
499*6000Sroot 			state = TS_DATA;
500*6000Sroot 			continue;
501*6000Sroot 
502*6000Sroot 		case TS_DO:
503*6000Sroot 			if (!myopts[c])
504*6000Sroot 				dooption(c);
505*6000Sroot 			state = TS_DATA;
506*6000Sroot 			continue;
507*6000Sroot 
508*6000Sroot 		case TS_DONT:
509*6000Sroot 			if (myopts[c]) {
510*6000Sroot 				myopts[c] = 0;
511*6000Sroot 				sprintf(nfrontp, wont, c);
512*6000Sroot 				nfrontp += sizeof(wont) - 2;
513*6000Sroot 			}
514*6000Sroot 			state = TS_DATA;
515*6000Sroot 			continue;
516*6000Sroot 		}
517*6000Sroot 	}
518*6000Sroot }
519*6000Sroot 
520*6000Sroot willoption(option)
521*6000Sroot 	int option;
522*6000Sroot {
523*6000Sroot 	char *fmt;
524*6000Sroot 
525*6000Sroot 	switch (option) {
526*6000Sroot 
527*6000Sroot 	case TELOPT_ECHO:
528*6000Sroot 		mode(1);
529*6000Sroot 
530*6000Sroot 	case TELOPT_SGA:
531*6000Sroot 		hisopts[option] = 1;
532*6000Sroot 		fmt = doopt;
533*6000Sroot 		break;
534*6000Sroot 
535*6000Sroot 	case TELOPT_TM:
536*6000Sroot 		fmt = dont;
537*6000Sroot 		break;
538*6000Sroot 
539*6000Sroot 	default:
540*6000Sroot 		fmt = dont;
541*6000Sroot 		break;
542*6000Sroot 	}
543*6000Sroot 	sprintf(nfrontp, dont, option);
544*6000Sroot 	nfrontp += sizeof(dont) - 2;
545*6000Sroot }
546*6000Sroot 
547*6000Sroot wontoption(option)
548*6000Sroot 	int option;
549*6000Sroot {
550*6000Sroot 	char *fmt;
551*6000Sroot 
552*6000Sroot 	switch (option) {
553*6000Sroot 
554*6000Sroot 	case TELOPT_ECHO:
555*6000Sroot 		mode(2);
556*6000Sroot 
557*6000Sroot 	case TELOPT_SGA:
558*6000Sroot 		hisopts[option] = 0;
559*6000Sroot 		fmt = dont;
560*6000Sroot 		break;
561*6000Sroot 
562*6000Sroot 	default:
563*6000Sroot 		fmt = dont;
564*6000Sroot 	}
565*6000Sroot 	sprintf(nfrontp, fmt, option);
566*6000Sroot 	nfrontp += sizeof(doopt) - 2;
567*6000Sroot }
568*6000Sroot 
569*6000Sroot dooption(option)
570*6000Sroot 	int option;
571*6000Sroot {
572*6000Sroot 	char *fmt;
573*6000Sroot 
574*6000Sroot 	switch (option) {
575*6000Sroot 
576*6000Sroot 	case TELOPT_TM:
577*6000Sroot 		fmt = wont;
578*6000Sroot 		break;
579*6000Sroot 
580*6000Sroot 	case TELOPT_SGA:
581*6000Sroot 		fmt = will;
582*6000Sroot 		break;
583*6000Sroot 
584*6000Sroot 	default:
585*6000Sroot 		fmt = wont;
586*6000Sroot 		break;
587*6000Sroot 	}
588*6000Sroot 	sprintf(nfrontp, fmt, option);
589*6000Sroot 	nfrontp += sizeof(doopt) - 2;
590*6000Sroot }
591*6000Sroot 
592*6000Sroot /*
593*6000Sroot  * Set the escape character.
594*6000Sroot  */
595*6000Sroot setescape(argc, argv)
596*6000Sroot 	int argc;
597*6000Sroot 	char *argv[];
598*6000Sroot {
599*6000Sroot 	register char *arg;
600*6000Sroot 	char buf[50];
601*6000Sroot 
602*6000Sroot 	if (argc > 2)
603*6000Sroot 		arg = argv[1];
604*6000Sroot 	else {
605*6000Sroot 		printf("new escape character: ");
606*6000Sroot 		gets(buf);
607*6000Sroot 		arg = buf;
608*6000Sroot 	}
609*6000Sroot 	if (arg[0] != '\0')
610*6000Sroot 		escape = arg[0];
611*6000Sroot 	printf("Escape character is '%s'.\n", control(escape));
612*6000Sroot }
613*6000Sroot 
614*6000Sroot /*
615*6000Sroot  * Construct a control character sequence
616*6000Sroot  * for a special character.
617*6000Sroot  */
618*6000Sroot char *
619*6000Sroot control(c)
620*6000Sroot 	register int c;
621*6000Sroot {
622*6000Sroot 	static char buf[3];
623*6000Sroot 
624*6000Sroot 	if (c == 0177)
625*6000Sroot 		return ("^?");
626*6000Sroot 	if (c >= 040) {
627*6000Sroot 		buf[0] = c;
628*6000Sroot 		buf[1] = 0;
629*6000Sroot 	} else {
630*6000Sroot 		buf[0] = '^';
631*6000Sroot 		buf[1] = '@'+c;
632*6000Sroot 		buf[2] = 0;
633*6000Sroot 	}
634*6000Sroot 	return (buf);
635*6000Sroot }
636*6000Sroot 
637*6000Sroot struct cmd *
638*6000Sroot getcmd(name)
639*6000Sroot 	register char *name;
640*6000Sroot {
641*6000Sroot 	register char *p, *q;
642*6000Sroot 	register struct cmd *c, *found;
643*6000Sroot 	register int nmatches, longest;
644*6000Sroot 
645*6000Sroot 	longest = 0;
646*6000Sroot 	nmatches = 0;
647*6000Sroot 	found = 0;
648*6000Sroot 	for (c = cmdtab; p = c->name; c++) {
649*6000Sroot 		for (q = name; *q == *p++; q++)
650*6000Sroot 			if (*q == 0)		/* exact match? */
651*6000Sroot 				return (c);
652*6000Sroot 		if (!*q) {			/* the name was a prefix */
653*6000Sroot 			if (q - name > longest) {
654*6000Sroot 				longest = q - name;
655*6000Sroot 				nmatches = 1;
656*6000Sroot 				found = c;
657*6000Sroot 			} else if (q - name == longest)
658*6000Sroot 				nmatches++;
659*6000Sroot 		}
660*6000Sroot 	}
661*6000Sroot 	if (nmatches > 1)
662*6000Sroot 		return ((struct cmd *)-1);
663*6000Sroot 	return (found);
664*6000Sroot }
665*6000Sroot 
666*6000Sroot deadpeer()
667*6000Sroot {
668*6000Sroot 	sigset(SIGPIPE, deadpeer);
669*6000Sroot 	mode(0);
670*6000Sroot 	longjmp(peerdied, -1);
671*6000Sroot }
672*6000Sroot 
673*6000Sroot intr()
674*6000Sroot {
675*6000Sroot 	sigset(SIGINT, intr);
676*6000Sroot 	mode(0);
677*6000Sroot 	longjmp(toplevel, -1);
678*6000Sroot }
679*6000Sroot 
680*6000Sroot ttyflush(fd)
681*6000Sroot {
682*6000Sroot 	int n;
683*6000Sroot 
684*6000Sroot 	if ((n = tfrontp - tbackp) > 0)
685*6000Sroot 		n = write(fd, tbackp, n);
686*6000Sroot 	if (n < 0 && errno == EWOULDBLOCK)
687*6000Sroot 		n = 0;
688*6000Sroot 	tbackp += n;
689*6000Sroot 	if (tbackp == tfrontp)
690*6000Sroot 		tbackp = tfrontp = ttyobuf;
691*6000Sroot }
692*6000Sroot 
693*6000Sroot netflush(fd)
694*6000Sroot {
695*6000Sroot 	int n;
696*6000Sroot 
697*6000Sroot 	if ((n = nfrontp - nbackp) > 0)
698*6000Sroot 		n = write(fd, nbackp, n);
699*6000Sroot 	if (n < 0 && errno == EWOULDBLOCK)
700*6000Sroot 		n = 0;
701*6000Sroot 	nbackp += n;
702*6000Sroot 	if (nbackp == nfrontp)
703*6000Sroot 		nbackp = nfrontp = netobuf;
704*6000Sroot }
705