xref: /original-bsd/libexec/telnetd/state.c (revision 58b1b499)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)state.c	8.4 (Berkeley) 02/20/95";
10 #endif /* not lint */
11 
12 #include "telnetd.h"
13 #if	defined(AUTHENTICATION)
14 #include <libtelnet/auth.h>
15 #endif
16 
17 unsigned char	doopt[] = { IAC, DO, '%', 'c', 0 };
18 unsigned char	dont[] = { IAC, DONT, '%', 'c', 0 };
19 unsigned char	will[] = { IAC, WILL, '%', 'c', 0 };
20 unsigned char	wont[] = { IAC, WONT, '%', 'c', 0 };
21 int	not42 = 1;
22 
23 /*
24  * Buffer for sub-options, and macros
25  * for suboptions buffer manipulations
26  */
27 unsigned char subbuffer[512], *subpointer= subbuffer, *subend= subbuffer;
28 
29 #define	SB_CLEAR()	subpointer = subbuffer
30 #define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
31 #define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \
32 				*subpointer++ = (c); \
33 			}
34 #define	SB_GET()	((*subpointer++)&0xff)
35 #define	SB_EOF()	(subpointer >= subend)
36 #define	SB_LEN()	(subend - subpointer)
37 
38 #ifdef	ENV_HACK
39 unsigned char *subsave;
40 #define SB_SAVE()	subsave = subpointer;
41 #define	SB_RESTORE()	subpointer = subsave;
42 #endif
43 
44 
45 /*
46  * State for recv fsm
47  */
48 #define	TS_DATA		0	/* base state */
49 #define	TS_IAC		1	/* look for double IAC's */
50 #define	TS_CR		2	/* CR-LF ->'s CR */
51 #define	TS_SB		3	/* throw away begin's... */
52 #define	TS_SE		4	/* ...end's (suboption negotiation) */
53 #define	TS_WILL		5	/* will option negotiation */
54 #define	TS_WONT		6	/* wont " */
55 #define	TS_DO		7	/* do " */
56 #define	TS_DONT		8	/* dont " */
57 
58 	void
59 telrcv()
60 {
61 	register int c;
62 	static int state = TS_DATA;
63 #if	defined(CRAY2) && defined(UNICOS5)
64 	char *opfrontp = pfrontp;
65 #endif
66 
67 	while (ncc > 0) {
68 		if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
69 			break;
70 		c = *netip++ & 0377, ncc--;
71 #ifdef	ENCRYPTION
72 		if (decrypt_input)
73 			c = (*decrypt_input)(c);
74 #endif	/* ENCRYPTION */
75 		switch (state) {
76 
77 		case TS_CR:
78 			state = TS_DATA;
79 			/* Strip off \n or \0 after a \r */
80 			if ((c == 0) || (c == '\n')) {
81 				break;
82 			}
83 			/* FALL THROUGH */
84 
85 		case TS_DATA:
86 			if (c == IAC) {
87 				state = TS_IAC;
88 				break;
89 			}
90 			/*
91 			 * We now map \r\n ==> \r for pragmatic reasons.
92 			 * Many client implementations send \r\n when
93 			 * the user hits the CarriageReturn key.
94 			 *
95 			 * We USED to map \r\n ==> \n, since \r\n says
96 			 * that we want to be in column 1 of the next
97 			 * printable line, and \n is the standard
98 			 * unix way of saying that (\r is only good
99 			 * if CRMOD is set, which it normally is).
100 			 */
101 			if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {
102 				int nc = *netip;
103 #ifdef	ENCRYPTION
104 				if (decrypt_input)
105 					nc = (*decrypt_input)(nc & 0xff);
106 #endif	/* ENCRYPTION */
107 #ifdef	LINEMODE
108 				/*
109 				 * If we are operating in linemode,
110 				 * convert to local end-of-line.
111 				 */
112 				if (linemode && (ncc > 0) && (('\n' == nc) ||
113 					 ((0 == nc) && tty_iscrnl())) ) {
114 					netip++; ncc--;
115 					c = '\n';
116 				} else
117 #endif
118 				{
119 #ifdef	ENCRYPTION
120 					if (decrypt_input)
121 						(void)(*decrypt_input)(-1);
122 #endif	/* ENCRYPTION */
123 					state = TS_CR;
124 				}
125 			}
126 			*pfrontp++ = c;
127 			break;
128 
129 		case TS_IAC:
130 gotiac:			switch (c) {
131 
132 			/*
133 			 * Send the process on the pty side an
134 			 * interrupt.  Do this with a NULL or
135 			 * interrupt char; depending on the tty mode.
136 			 */
137 			case IP:
138 				DIAG(TD_OPTIONS,
139 					printoption("td: recv IAC", c));
140 				interrupt();
141 				break;
142 
143 			case BREAK:
144 				DIAG(TD_OPTIONS,
145 					printoption("td: recv IAC", c));
146 				sendbrk();
147 				break;
148 
149 			/*
150 			 * Are You There?
151 			 */
152 			case AYT:
153 				DIAG(TD_OPTIONS,
154 					printoption("td: recv IAC", c));
155 				recv_ayt();
156 				break;
157 
158 			/*
159 			 * Abort Output
160 			 */
161 			case AO:
162 			    {
163 				DIAG(TD_OPTIONS,
164 					printoption("td: recv IAC", c));
165 				ptyflush();	/* half-hearted */
166 				init_termbuf();
167 
168 				if (slctab[SLC_AO].sptr &&
169 				    *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
170 				    *pfrontp++ =
171 					(unsigned char)*slctab[SLC_AO].sptr;
172 				}
173 
174 				netclear();	/* clear buffer back */
175 				*nfrontp++ = IAC;
176 				*nfrontp++ = DM;
177 				neturg = nfrontp-1; /* off by one XXX */
178 				DIAG(TD_OPTIONS,
179 					printoption("td: send IAC", DM));
180 				break;
181 			    }
182 
183 			/*
184 			 * Erase Character and
185 			 * Erase Line
186 			 */
187 			case EC:
188 			case EL:
189 			    {
190 				cc_t ch;
191 
192 				DIAG(TD_OPTIONS,
193 					printoption("td: recv IAC", c));
194 				ptyflush();	/* half-hearted */
195 				init_termbuf();
196 				if (c == EC)
197 					ch = *slctab[SLC_EC].sptr;
198 				else
199 					ch = *slctab[SLC_EL].sptr;
200 				if (ch != (cc_t)(_POSIX_VDISABLE))
201 					*pfrontp++ = (unsigned char)ch;
202 				break;
203 			    }
204 
205 			/*
206 			 * Check for urgent data...
207 			 */
208 			case DM:
209 				DIAG(TD_OPTIONS,
210 					printoption("td: recv IAC", c));
211 				SYNCHing = stilloob(net);
212 				settimer(gotDM);
213 				break;
214 
215 
216 			/*
217 			 * Begin option subnegotiation...
218 			 */
219 			case SB:
220 				state = TS_SB;
221 				SB_CLEAR();
222 				continue;
223 
224 			case WILL:
225 				state = TS_WILL;
226 				continue;
227 
228 			case WONT:
229 				state = TS_WONT;
230 				continue;
231 
232 			case DO:
233 				state = TS_DO;
234 				continue;
235 
236 			case DONT:
237 				state = TS_DONT;
238 				continue;
239 			case EOR:
240 				if (his_state_is_will(TELOPT_EOR))
241 					doeof();
242 				break;
243 
244 			/*
245 			 * Handle RFC 10xx Telnet linemode option additions
246 			 * to command stream (EOF, SUSP, ABORT).
247 			 */
248 			case xEOF:
249 				doeof();
250 				break;
251 
252 			case SUSP:
253 				sendsusp();
254 				break;
255 
256 			case ABORT:
257 				sendbrk();
258 				break;
259 
260 			case IAC:
261 				*pfrontp++ = c;
262 				break;
263 			}
264 			state = TS_DATA;
265 			break;
266 
267 		case TS_SB:
268 			if (c == IAC) {
269 				state = TS_SE;
270 			} else {
271 				SB_ACCUM(c);
272 			}
273 			break;
274 
275 		case TS_SE:
276 			if (c != SE) {
277 				if (c != IAC) {
278 					/*
279 					 * bad form of suboption negotiation.
280 					 * handle it in such a way as to avoid
281 					 * damage to local state.  Parse
282 					 * suboption buffer found so far,
283 					 * then treat remaining stream as
284 					 * another command sequence.
285 					 */
286 
287 					/* for DIAGNOSTICS */
288 					SB_ACCUM(IAC);
289 					SB_ACCUM(c);
290 					subpointer -= 2;
291 
292 					SB_TERM();
293 					suboption();
294 					state = TS_IAC;
295 					goto gotiac;
296 				}
297 				SB_ACCUM(c);
298 				state = TS_SB;
299 			} else {
300 				/* for DIAGNOSTICS */
301 				SB_ACCUM(IAC);
302 				SB_ACCUM(SE);
303 				subpointer -= 2;
304 
305 				SB_TERM();
306 				suboption();	/* handle sub-option */
307 				state = TS_DATA;
308 			}
309 			break;
310 
311 		case TS_WILL:
312 			willoption(c);
313 			state = TS_DATA;
314 			continue;
315 
316 		case TS_WONT:
317 			wontoption(c);
318 			state = TS_DATA;
319 			continue;
320 
321 		case TS_DO:
322 			dooption(c);
323 			state = TS_DATA;
324 			continue;
325 
326 		case TS_DONT:
327 			dontoption(c);
328 			state = TS_DATA;
329 			continue;
330 
331 		default:
332 			syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
333 			printf("telnetd: panic state=%d\n", state);
334 			exit(1);
335 		}
336 	}
337 #if	defined(CRAY2) && defined(UNICOS5)
338 	if (!linemode) {
339 		char	xptyobuf[BUFSIZ+NETSLOP];
340 		char	xbuf2[BUFSIZ];
341 		register char *cp;
342 		int n = pfrontp - opfrontp, oc;
343 		bcopy(opfrontp, xptyobuf, n);
344 		pfrontp = opfrontp;
345 		pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP,
346 					xbuf2, &oc, BUFSIZ);
347 		for (cp = xbuf2; oc > 0; --oc)
348 			if ((*nfrontp++ = *cp++) == IAC)
349 				*nfrontp++ = IAC;
350 	}
351 #endif	/* defined(CRAY2) && defined(UNICOS5) */
352 }  /* end of telrcv */
353 
354 /*
355  * The will/wont/do/dont state machines are based on Dave Borman's
356  * Telnet option processing state machine.
357  *
358  * These correspond to the following states:
359  *	my_state = the last negotiated state
360  *	want_state = what I want the state to go to
361  *	want_resp = how many requests I have sent
362  * All state defaults are negative, and resp defaults to 0.
363  *
364  * When initiating a request to change state to new_state:
365  *
366  * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) {
367  *	do nothing;
368  * } else {
369  *	want_state = new_state;
370  *	send new_state;
371  *	want_resp++;
372  * }
373  *
374  * When receiving new_state:
375  *
376  * if (want_resp) {
377  *	want_resp--;
378  *	if (want_resp && (new_state == my_state))
379  *		want_resp--;
380  * }
381  * if ((want_resp == 0) && (new_state != want_state)) {
382  *	if (ok_to_switch_to new_state)
383  *		want_state = new_state;
384  *	else
385  *		want_resp++;
386  *	send want_state;
387  * }
388  * my_state = new_state;
389  *
390  * Note that new_state is implied in these functions by the function itself.
391  * will and do imply positive new_state, wont and dont imply negative.
392  *
393  * Finally, there is one catch.  If we send a negative response to a
394  * positive request, my_state will be the positive while want_state will
395  * remain negative.  my_state will revert to negative when the negative
396  * acknowlegment arrives from the peer.  Thus, my_state generally tells
397  * us not only the last negotiated state, but also tells us what the peer
398  * wants to be doing as well.  It is important to understand this difference
399  * as we may wish to be processing data streams based on our desired state
400  * (want_state) or based on what the peer thinks the state is (my_state).
401  *
402  * This all works fine because if the peer sends a positive request, the data
403  * that we receive prior to negative acknowlegment will probably be affected
404  * by the positive state, and we can process it as such (if we can; if we
405  * can't then it really doesn't matter).  If it is that important, then the
406  * peer probably should be buffering until this option state negotiation
407  * is complete.
408  *
409  */
410 	void
411 send_do(option, init)
412 	int option, init;
413 {
414 	if (init) {
415 		if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
416 		    his_want_state_is_will(option))
417 			return;
418 		/*
419 		 * Special case for TELOPT_TM:  We send a DO, but pretend
420 		 * that we sent a DONT, so that we can send more DOs if
421 		 * we want to.
422 		 */
423 		if (option == TELOPT_TM)
424 			set_his_want_state_wont(option);
425 		else
426 			set_his_want_state_will(option);
427 		do_dont_resp[option]++;
428 	}
429 	(void) sprintf(nfrontp, (char *)doopt, option);
430 	nfrontp += sizeof (dont) - 2;
431 
432 	DIAG(TD_OPTIONS, printoption("td: send do", option));
433 }
434 
435 #ifdef	AUTHENTICATION
436 extern void auth_request();
437 #endif
438 #ifdef	LINEMODE
439 extern void doclientstat();
440 #endif
441 #ifdef	ENCRYPTION
442 extern void encrypt_send_support();
443 #endif	/* ENCRYPTION */
444 
445 	void
446 willoption(option)
447 	int option;
448 {
449 	int changeok = 0;
450 	void (*func)() = 0;
451 
452 	/*
453 	 * process input from peer.
454 	 */
455 
456 	DIAG(TD_OPTIONS, printoption("td: recv will", option));
457 
458 	if (do_dont_resp[option]) {
459 		do_dont_resp[option]--;
460 		if (do_dont_resp[option] && his_state_is_will(option))
461 			do_dont_resp[option]--;
462 	}
463 	if (do_dont_resp[option] == 0) {
464 	    if (his_want_state_is_wont(option)) {
465 		switch (option) {
466 
467 		case TELOPT_BINARY:
468 			init_termbuf();
469 			tty_binaryin(1);
470 			set_termbuf();
471 			changeok++;
472 			break;
473 
474 		case TELOPT_ECHO:
475 			/*
476 			 * See comments below for more info.
477 			 */
478 			not42 = 0;	/* looks like a 4.2 system */
479 			break;
480 
481 		case TELOPT_TM:
482 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
483 			/*
484 			 * This telnetd implementation does not really
485 			 * support timing marks, it just uses them to
486 			 * support the kludge linemode stuff.  If we
487 			 * receive a will or wont TM in response to our
488 			 * do TM request that may have been sent to
489 			 * determine kludge linemode support, process
490 			 * it, otherwise TM should get a negative
491 			 * response back.
492 			 */
493 			/*
494 			 * Handle the linemode kludge stuff.
495 			 * If we are not currently supporting any
496 			 * linemode at all, then we assume that this
497 			 * is the client telling us to use kludge
498 			 * linemode in response to our query.  Set the
499 			 * linemode type that is to be supported, note
500 			 * that the client wishes to use linemode, and
501 			 * eat the will TM as though it never arrived.
502 			 */
503 			if (lmodetype < KLUDGE_LINEMODE) {
504 				lmodetype = KLUDGE_LINEMODE;
505 				clientstat(TELOPT_LINEMODE, WILL, 0);
506 				send_wont(TELOPT_SGA, 1);
507 			} else if (lmodetype == NO_AUTOKLUDGE) {
508 				lmodetype = KLUDGE_OK;
509 			}
510 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
511 			/*
512 			 * We never respond to a WILL TM, and
513 			 * we leave the state WONT.
514 			 */
515 			return;
516 
517 		case TELOPT_LFLOW:
518 			/*
519 			 * If we are going to support flow control
520 			 * option, then don't worry peer that we can't
521 			 * change the flow control characters.
522 			 */
523 			slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
524 			slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
525 			slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
526 			slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
527 		case TELOPT_TTYPE:
528 		case TELOPT_SGA:
529 		case TELOPT_NAWS:
530 		case TELOPT_TSPEED:
531 		case TELOPT_XDISPLOC:
532 		case TELOPT_NEW_ENVIRON:
533 		case TELOPT_OLD_ENVIRON:
534 			changeok++;
535 			break;
536 
537 #ifdef	LINEMODE
538 		case TELOPT_LINEMODE:
539 # ifdef	KLUDGELINEMODE
540 			/*
541 			 * Note client's desire to use linemode.
542 			 */
543 			lmodetype = REAL_LINEMODE;
544 # endif	/* KLUDGELINEMODE */
545 			func = doclientstat;
546 			changeok++;
547 			break;
548 #endif	/* LINEMODE */
549 
550 #ifdef	AUTHENTICATION
551 		case TELOPT_AUTHENTICATION:
552 			func = auth_request;
553 			changeok++;
554 			break;
555 #endif
556 
557 #ifdef	ENCRYPTION
558 		case TELOPT_ENCRYPT:
559 			func = encrypt_send_support;
560 			changeok++;
561 			break;
562 #endif	/* ENCRYPTION */
563 
564 		default:
565 			break;
566 		}
567 		if (changeok) {
568 			set_his_want_state_will(option);
569 			send_do(option, 0);
570 		} else {
571 			do_dont_resp[option]++;
572 			send_dont(option, 0);
573 		}
574 	    } else {
575 		/*
576 		 * Option processing that should happen when
577 		 * we receive conformation of a change in
578 		 * state that we had requested.
579 		 */
580 		switch (option) {
581 		case TELOPT_ECHO:
582 			not42 = 0;	/* looks like a 4.2 system */
583 			/*
584 			 * Egads, he responded "WILL ECHO".  Turn
585 			 * it off right now!
586 			 */
587 			send_dont(option, 1);
588 			/*
589 			 * "WILL ECHO".  Kludge upon kludge!
590 			 * A 4.2 client is now echoing user input at
591 			 * the tty.  This is probably undesireable and
592 			 * it should be stopped.  The client will
593 			 * respond WONT TM to the DO TM that we send to
594 			 * check for kludge linemode.  When the WONT TM
595 			 * arrives, linemode will be turned off and a
596 			 * change propogated to the pty.  This change
597 			 * will cause us to process the new pty state
598 			 * in localstat(), which will notice that
599 			 * linemode is off and send a WILL ECHO
600 			 * so that we are properly in character mode and
601 			 * all is well.
602 			 */
603 			break;
604 #ifdef	LINEMODE
605 		case TELOPT_LINEMODE:
606 # ifdef	KLUDGELINEMODE
607 			/*
608 			 * Note client's desire to use linemode.
609 			 */
610 			lmodetype = REAL_LINEMODE;
611 # endif	/* KLUDGELINEMODE */
612 			func = doclientstat;
613 			break;
614 #endif	/* LINEMODE */
615 
616 #ifdef	AUTHENTICATION
617 		case TELOPT_AUTHENTICATION:
618 			func = auth_request;
619 			break;
620 #endif
621 
622 #ifdef	ENCRYPTION
623 		case TELOPT_ENCRYPT:
624 			func = encrypt_send_support;
625 			break;
626 #endif	/* ENCRYPTION */
627 		case TELOPT_LFLOW:
628 			func = flowstat;
629 			break;
630 		}
631 	    }
632 	}
633 	set_his_state_will(option);
634 	if (func)
635 		(*func)();
636 }  /* end of willoption */
637 
638 	void
639 send_dont(option, init)
640 	int option, init;
641 {
642 	if (init) {
643 		if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) ||
644 		    his_want_state_is_wont(option))
645 			return;
646 		set_his_want_state_wont(option);
647 		do_dont_resp[option]++;
648 	}
649 	(void) sprintf(nfrontp, (char *)dont, option);
650 	nfrontp += sizeof (doopt) - 2;
651 
652 	DIAG(TD_OPTIONS, printoption("td: send dont", option));
653 }
654 
655 	void
656 wontoption(option)
657 	int option;
658 {
659 	/*
660 	 * Process client input.
661 	 */
662 
663 	DIAG(TD_OPTIONS, printoption("td: recv wont", option));
664 
665 	if (do_dont_resp[option]) {
666 		do_dont_resp[option]--;
667 		if (do_dont_resp[option] && his_state_is_wont(option))
668 			do_dont_resp[option]--;
669 	}
670 	if (do_dont_resp[option] == 0) {
671 	    if (his_want_state_is_will(option)) {
672 		/* it is always ok to change to negative state */
673 		switch (option) {
674 		case TELOPT_ECHO:
675 			not42 = 1; /* doesn't seem to be a 4.2 system */
676 			break;
677 
678 		case TELOPT_BINARY:
679 			init_termbuf();
680 			tty_binaryin(0);
681 			set_termbuf();
682 			break;
683 
684 #ifdef	LINEMODE
685 		case TELOPT_LINEMODE:
686 # ifdef	KLUDGELINEMODE
687 			/*
688 			 * If real linemode is supported, then client is
689 			 * asking to turn linemode off.
690 			 */
691 			if (lmodetype != REAL_LINEMODE)
692 				break;
693 # endif	/* KLUDGELINEMODE */
694 			clientstat(TELOPT_LINEMODE, WONT, 0);
695 			break;
696 #endif	/* LINEMODE */
697 
698 		case TELOPT_TM:
699 			/*
700 			 * If we get a WONT TM, and had sent a DO TM,
701 			 * don't respond with a DONT TM, just leave it
702 			 * as is.  Short circut the state machine to
703 			 * achive this.
704 			 */
705 			set_his_want_state_wont(TELOPT_TM);
706 			return;
707 
708 		case TELOPT_LFLOW:
709 			/*
710 			 * If we are not going to support flow control
711 			 * option, then let peer know that we can't
712 			 * change the flow control characters.
713 			 */
714 			slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
715 			slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
716 			slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
717 			slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
718 			break;
719 
720 #if	defined(AUTHENTICATION)
721 		case TELOPT_AUTHENTICATION:
722 			auth_finished(0, AUTH_REJECT);
723 			break;
724 #endif
725 
726 		/*
727 		 * For options that we might spin waiting for
728 		 * sub-negotiation, if the client turns off the
729 		 * option rather than responding to the request,
730 		 * we have to treat it here as if we got a response
731 		 * to the sub-negotiation, (by updating the timers)
732 		 * so that we'll break out of the loop.
733 		 */
734 		case TELOPT_TTYPE:
735 			settimer(ttypesubopt);
736 			break;
737 
738 		case TELOPT_TSPEED:
739 			settimer(tspeedsubopt);
740 			break;
741 
742 		case TELOPT_XDISPLOC:
743 			settimer(xdisplocsubopt);
744 			break;
745 
746 		case TELOPT_OLD_ENVIRON:
747 			settimer(oenvironsubopt);
748 			break;
749 
750 		case TELOPT_NEW_ENVIRON:
751 			settimer(environsubopt);
752 			break;
753 
754 		default:
755 			break;
756 		}
757 		set_his_want_state_wont(option);
758 		if (his_state_is_will(option))
759 			send_dont(option, 0);
760 	    } else {
761 		switch (option) {
762 		case TELOPT_TM:
763 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
764 			if (lmodetype < NO_AUTOKLUDGE) {
765 				lmodetype = NO_LINEMODE;
766 				clientstat(TELOPT_LINEMODE, WONT, 0);
767 				send_will(TELOPT_SGA, 1);
768 				send_will(TELOPT_ECHO, 1);
769 			}
770 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
771 			break;
772 
773 #if	defined(AUTHENTICATION)
774 		case TELOPT_AUTHENTICATION:
775 			auth_finished(0, AUTH_REJECT);
776 			break;
777 #endif
778 		default:
779 			break;
780 		}
781 	    }
782 	}
783 	set_his_state_wont(option);
784 
785 }  /* end of wontoption */
786 
787 	void
788 send_will(option, init)
789 	int option, init;
790 {
791 	if (init) {
792 		if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
793 		    my_want_state_is_will(option))
794 			return;
795 		set_my_want_state_will(option);
796 		will_wont_resp[option]++;
797 	}
798 	(void) sprintf(nfrontp, (char *)will, option);
799 	nfrontp += sizeof (doopt) - 2;
800 
801 	DIAG(TD_OPTIONS, printoption("td: send will", option));
802 }
803 
804 #if	!defined(LINEMODE) || !defined(KLUDGELINEMODE)
805 /*
806  * When we get a DONT SGA, we will try once to turn it
807  * back on.  If the other side responds DONT SGA, we
808  * leave it at that.  This is so that when we talk to
809  * clients that understand KLUDGELINEMODE but not LINEMODE,
810  * we'll keep them in char-at-a-time mode.
811  */
812 int turn_on_sga = 0;
813 #endif
814 
815 	void
816 dooption(option)
817 	int option;
818 {
819 	int changeok = 0;
820 
821 	/*
822 	 * Process client input.
823 	 */
824 
825 	DIAG(TD_OPTIONS, printoption("td: recv do", option));
826 
827 	if (will_wont_resp[option]) {
828 		will_wont_resp[option]--;
829 		if (will_wont_resp[option] && my_state_is_will(option))
830 			will_wont_resp[option]--;
831 	}
832 	if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
833 		switch (option) {
834 		case TELOPT_ECHO:
835 #ifdef	LINEMODE
836 # ifdef	KLUDGELINEMODE
837 			if (lmodetype == NO_LINEMODE)
838 # else
839 			if (his_state_is_wont(TELOPT_LINEMODE))
840 # endif
841 #endif
842 			{
843 				init_termbuf();
844 				tty_setecho(1);
845 				set_termbuf();
846 			}
847 			changeok++;
848 			break;
849 
850 		case TELOPT_BINARY:
851 			init_termbuf();
852 			tty_binaryout(1);
853 			set_termbuf();
854 			changeok++;
855 			break;
856 
857 		case TELOPT_SGA:
858 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
859 			/*
860 			 * If kludge linemode is in use, then we must
861 			 * process an incoming do SGA for linemode
862 			 * purposes.
863 			 */
864 			if (lmodetype == KLUDGE_LINEMODE) {
865 				/*
866 				 * Receipt of "do SGA" in kludge
867 				 * linemode is the peer asking us to
868 				 * turn off linemode.  Make note of
869 				 * the request.
870 				 */
871 				clientstat(TELOPT_LINEMODE, WONT, 0);
872 				/*
873 				 * If linemode did not get turned off
874 				 * then don't tell peer that we did.
875 				 * Breaking here forces a wont SGA to
876 				 * be returned.
877 				 */
878 				if (linemode)
879 					break;
880 			}
881 #else
882 			turn_on_sga = 0;
883 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
884 			changeok++;
885 			break;
886 
887 		case TELOPT_STATUS:
888 			changeok++;
889 			break;
890 
891 		case TELOPT_TM:
892 			/*
893 			 * Special case for TM.  We send a WILL, but
894 			 * pretend we sent a WONT.
895 			 */
896 			send_will(option, 0);
897 			set_my_want_state_wont(option);
898 			set_my_state_wont(option);
899 			return;
900 
901 		case TELOPT_LOGOUT:
902 			/*
903 			 * When we get a LOGOUT option, respond
904 			 * with a WILL LOGOUT, make sure that
905 			 * it gets written out to the network,
906 			 * and then just go away...
907 			 */
908 			set_my_want_state_will(TELOPT_LOGOUT);
909 			send_will(TELOPT_LOGOUT, 0);
910 			set_my_state_will(TELOPT_LOGOUT);
911 			(void)netflush();
912 			cleanup(0);
913 			/* NOT REACHED */
914 			break;
915 
916 #ifdef	ENCRYPTION
917 		case TELOPT_ENCRYPT:
918 			changeok++;
919 			break;
920 #endif	/* ENCRYPTION */
921 		case TELOPT_LINEMODE:
922 		case TELOPT_TTYPE:
923 		case TELOPT_NAWS:
924 		case TELOPT_TSPEED:
925 		case TELOPT_LFLOW:
926 		case TELOPT_XDISPLOC:
927 #ifdef	TELOPT_ENVIRON
928 		case TELOPT_NEW_ENVIRON:
929 #endif
930 		case TELOPT_OLD_ENVIRON:
931 		default:
932 			break;
933 		}
934 		if (changeok) {
935 			set_my_want_state_will(option);
936 			send_will(option, 0);
937 		} else {
938 			will_wont_resp[option]++;
939 			send_wont(option, 0);
940 		}
941 	}
942 	set_my_state_will(option);
943 
944 }  /* end of dooption */
945 
946 	void
947 send_wont(option, init)
948 	int option, init;
949 {
950 	if (init) {
951 		if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
952 		    my_want_state_is_wont(option))
953 			return;
954 		set_my_want_state_wont(option);
955 		will_wont_resp[option]++;
956 	}
957 	(void) sprintf(nfrontp, (char *)wont, option);
958 	nfrontp += sizeof (wont) - 2;
959 
960 	DIAG(TD_OPTIONS, printoption("td: send wont", option));
961 }
962 
963 	void
964 dontoption(option)
965 	int option;
966 {
967 	/*
968 	 * Process client input.
969 	 */
970 
971 
972 	DIAG(TD_OPTIONS, printoption("td: recv dont", option));
973 
974 	if (will_wont_resp[option]) {
975 		will_wont_resp[option]--;
976 		if (will_wont_resp[option] && my_state_is_wont(option))
977 			will_wont_resp[option]--;
978 	}
979 	if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
980 		switch (option) {
981 		case TELOPT_BINARY:
982 			init_termbuf();
983 			tty_binaryout(0);
984 			set_termbuf();
985 			break;
986 
987 		case TELOPT_ECHO:	/* we should stop echoing */
988 #ifdef	LINEMODE
989 # ifdef	KLUDGELINEMODE
990 			if ((lmodetype != REAL_LINEMODE) &&
991 			    (lmodetype != KLUDGE_LINEMODE))
992 # else
993 			if (his_state_is_wont(TELOPT_LINEMODE))
994 # endif
995 #endif
996 			{
997 				init_termbuf();
998 				tty_setecho(0);
999 				set_termbuf();
1000 			}
1001 			break;
1002 
1003 		case TELOPT_SGA:
1004 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
1005 			/*
1006 			 * If kludge linemode is in use, then we
1007 			 * must process an incoming do SGA for
1008 			 * linemode purposes.
1009 			 */
1010 			if ((lmodetype == KLUDGE_LINEMODE) ||
1011 			    (lmodetype == KLUDGE_OK)) {
1012 				/*
1013 				 * The client is asking us to turn
1014 				 * linemode on.
1015 				 */
1016 				lmodetype = KLUDGE_LINEMODE;
1017 				clientstat(TELOPT_LINEMODE, WILL, 0);
1018 				/*
1019 				 * If we did not turn line mode on,
1020 				 * then what do we say?  Will SGA?
1021 				 * This violates design of telnet.
1022 				 * Gross.  Very Gross.
1023 				 */
1024 			}
1025 			break;
1026 #else
1027 			set_my_want_state_wont(option);
1028 			if (my_state_is_will(option))
1029 				send_wont(option, 0);
1030 			set_my_state_wont(option);
1031 			if (turn_on_sga ^= 1)
1032 				send_will(option, 1);
1033 			return;
1034 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
1035 
1036 		default:
1037 			break;
1038 		}
1039 
1040 		set_my_want_state_wont(option);
1041 		if (my_state_is_will(option))
1042 			send_wont(option, 0);
1043 	}
1044 	set_my_state_wont(option);
1045 
1046 }  /* end of dontoption */
1047 
1048 #ifdef	ENV_HACK
1049 int env_ovar = -1;
1050 int env_ovalue = -1;
1051 #else	/* ENV_HACK */
1052 # define env_ovar OLD_ENV_VAR
1053 # define env_ovalue OLD_ENV_VALUE
1054 #endif	/* ENV_HACK */
1055 
1056 /*
1057  * suboption()
1058  *
1059  *	Look at the sub-option buffer, and try to be helpful to the other
1060  * side.
1061  *
1062  *	Currently we recognize:
1063  *
1064  *	Terminal type is
1065  *	Linemode
1066  *	Window size
1067  *	Terminal speed
1068  */
1069 	void
1070 suboption()
1071 {
1072     register int subchar;
1073 
1074     DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
1075 
1076     subchar = SB_GET();
1077     switch (subchar) {
1078     case TELOPT_TSPEED: {
1079 	register int xspeed, rspeed;
1080 
1081 	if (his_state_is_wont(TELOPT_TSPEED))	/* Ignore if option disabled */
1082 		break;
1083 
1084 	settimer(tspeedsubopt);
1085 
1086 	if (SB_EOF() || SB_GET() != TELQUAL_IS)
1087 		return;
1088 
1089 	xspeed = atoi((char *)subpointer);
1090 
1091 	while (SB_GET() != ',' && !SB_EOF());
1092 	if (SB_EOF())
1093 		return;
1094 
1095 	rspeed = atoi((char *)subpointer);
1096 	clientstat(TELOPT_TSPEED, xspeed, rspeed);
1097 
1098 	break;
1099 
1100     }  /* end of case TELOPT_TSPEED */
1101 
1102     case TELOPT_TTYPE: {		/* Yaaaay! */
1103 	static char terminalname[41];
1104 
1105 	if (his_state_is_wont(TELOPT_TTYPE))	/* Ignore if option disabled */
1106 		break;
1107 	settimer(ttypesubopt);
1108 
1109 	if (SB_EOF() || SB_GET() != TELQUAL_IS) {
1110 	    return;		/* ??? XXX but, this is the most robust */
1111 	}
1112 
1113 	terminaltype = terminalname;
1114 
1115 	while ((terminaltype < (terminalname + sizeof terminalname-1)) &&
1116 								    !SB_EOF()) {
1117 	    register int c;
1118 
1119 	    c = SB_GET();
1120 	    if (isupper(c)) {
1121 		c = tolower(c);
1122 	    }
1123 	    *terminaltype++ = c;    /* accumulate name */
1124 	}
1125 	*terminaltype = 0;
1126 	terminaltype = terminalname;
1127 	break;
1128     }  /* end of case TELOPT_TTYPE */
1129 
1130     case TELOPT_NAWS: {
1131 	register int xwinsize, ywinsize;
1132 
1133 	if (his_state_is_wont(TELOPT_NAWS))	/* Ignore if option disabled */
1134 		break;
1135 
1136 	if (SB_EOF())
1137 		return;
1138 	xwinsize = SB_GET() << 8;
1139 	if (SB_EOF())
1140 		return;
1141 	xwinsize |= SB_GET();
1142 	if (SB_EOF())
1143 		return;
1144 	ywinsize = SB_GET() << 8;
1145 	if (SB_EOF())
1146 		return;
1147 	ywinsize |= SB_GET();
1148 	clientstat(TELOPT_NAWS, xwinsize, ywinsize);
1149 
1150 	break;
1151 
1152     }  /* end of case TELOPT_NAWS */
1153 
1154 #ifdef	LINEMODE
1155     case TELOPT_LINEMODE: {
1156 	register int request;
1157 
1158 	if (his_state_is_wont(TELOPT_LINEMODE))	/* Ignore if option disabled */
1159 		break;
1160 	/*
1161 	 * Process linemode suboptions.
1162 	 */
1163 	if (SB_EOF())
1164 	    break;		/* garbage was sent */
1165 	request = SB_GET();	/* get will/wont */
1166 
1167 	if (SB_EOF())
1168 	    break;		/* another garbage check */
1169 
1170 	if (request == LM_SLC) {  /* SLC is not preceeded by WILL or WONT */
1171 		/*
1172 		 * Process suboption buffer of slc's
1173 		 */
1174 		start_slc(1);
1175 		do_opt_slc(subpointer, subend - subpointer);
1176 		(void) end_slc(0);
1177 		break;
1178 	} else if (request == LM_MODE) {
1179 		if (SB_EOF())
1180 		    return;
1181 		useeditmode = SB_GET();  /* get mode flag */
1182 		clientstat(LM_MODE, 0, 0);
1183 		break;
1184 	}
1185 
1186 	if (SB_EOF())
1187 	    break;
1188 	switch (SB_GET()) {  /* what suboption? */
1189 	case LM_FORWARDMASK:
1190 		/*
1191 		 * According to spec, only server can send request for
1192 		 * forwardmask, and client can only return a positive response.
1193 		 * So don't worry about it.
1194 		 */
1195 
1196 	default:
1197 		break;
1198 	}
1199 	break;
1200     }  /* end of case TELOPT_LINEMODE */
1201 #endif
1202     case TELOPT_STATUS: {
1203 	int mode;
1204 
1205 	if (SB_EOF())
1206 	    break;
1207 	mode = SB_GET();
1208 	switch (mode) {
1209 	case TELQUAL_SEND:
1210 	    if (my_state_is_will(TELOPT_STATUS))
1211 		send_status();
1212 	    break;
1213 
1214 	case TELQUAL_IS:
1215 	    break;
1216 
1217 	default:
1218 	    break;
1219 	}
1220 	break;
1221     }  /* end of case TELOPT_STATUS */
1222 
1223     case TELOPT_XDISPLOC: {
1224 	if (SB_EOF() || SB_GET() != TELQUAL_IS)
1225 		return;
1226 	settimer(xdisplocsubopt);
1227 	subpointer[SB_LEN()] = '\0';
1228 	(void)setenv("DISPLAY", (char *)subpointer, 1);
1229 	break;
1230     }  /* end of case TELOPT_XDISPLOC */
1231 
1232 #ifdef	TELOPT_NEW_ENVIRON
1233     case TELOPT_NEW_ENVIRON:
1234 #endif
1235     case TELOPT_OLD_ENVIRON: {
1236 	register int c;
1237 	register char *cp, *varp, *valp;
1238 
1239 	if (SB_EOF())
1240 		return;
1241 	c = SB_GET();
1242 	if (c == TELQUAL_IS) {
1243 		if (subchar == TELOPT_OLD_ENVIRON)
1244 			settimer(oenvironsubopt);
1245 		else
1246 			settimer(environsubopt);
1247 	} else if (c != TELQUAL_INFO) {
1248 		return;
1249 	}
1250 
1251 #ifdef	TELOPT_NEW_ENVIRON
1252 	if (subchar == TELOPT_NEW_ENVIRON) {
1253 	    while (!SB_EOF()) {
1254 		c = SB_GET();
1255 		if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
1256 			break;
1257 	    }
1258 	} else
1259 #endif
1260 	{
1261 #ifdef	ENV_HACK
1262 	    /*
1263 	     * We only want to do this if we haven't already decided
1264 	     * whether or not the other side has its VALUE and VAR
1265 	     * reversed.
1266 	     */
1267 	    if (env_ovar < 0) {
1268 		register int last = -1;		/* invalid value */
1269 		int empty = 0;
1270 		int got_var = 0, got_value = 0, got_uservar = 0;
1271 
1272 		/*
1273 		 * The other side might have its VALUE and VAR values
1274 		 * reversed.  To be interoperable, we need to determine
1275 		 * which way it is.  If the first recognized character
1276 		 * is a VAR or VALUE, then that will tell us what
1277 		 * type of client it is.  If the fist recognized
1278 		 * character is a USERVAR, then we continue scanning
1279 		 * the suboption looking for two consecutive
1280 		 * VAR or VALUE fields.  We should not get two
1281 		 * consecutive VALUE fields, so finding two
1282 		 * consecutive VALUE or VAR fields will tell us
1283 		 * what the client is.
1284 		 */
1285 		SB_SAVE();
1286 		while (!SB_EOF()) {
1287 			c = SB_GET();
1288 			switch(c) {
1289 			case OLD_ENV_VAR:
1290 				if (last < 0 || last == OLD_ENV_VAR
1291 				    || (empty && (last == OLD_ENV_VALUE)))
1292 					goto env_ovar_ok;
1293 				got_var++;
1294 				last = OLD_ENV_VAR;
1295 				break;
1296 			case OLD_ENV_VALUE:
1297 				if (last < 0 || last == OLD_ENV_VALUE
1298 				    || (empty && (last == OLD_ENV_VAR)))
1299 					goto env_ovar_wrong;
1300 				got_value++;
1301 				last = OLD_ENV_VALUE;
1302 				break;
1303 			case ENV_USERVAR:
1304 				/* count strings of USERVAR as one */
1305 				if (last != ENV_USERVAR)
1306 					got_uservar++;
1307 				if (empty) {
1308 					if (last == OLD_ENV_VALUE)
1309 						goto env_ovar_ok;
1310 					if (last == OLD_ENV_VAR)
1311 						goto env_ovar_wrong;
1312 				}
1313 				last = ENV_USERVAR;
1314 				break;
1315 			case ENV_ESC:
1316 				if (!SB_EOF())
1317 					c = SB_GET();
1318 				/* FALL THROUGH */
1319 			default:
1320 				empty = 0;
1321 				continue;
1322 			}
1323 			empty = 1;
1324 		}
1325 		if (empty) {
1326 			if (last == OLD_ENV_VALUE)
1327 				goto env_ovar_ok;
1328 			if (last == OLD_ENV_VAR)
1329 				goto env_ovar_wrong;
1330 		}
1331 		/*
1332 		 * Ok, the first thing was a USERVAR, and there
1333 		 * are not two consecutive VAR or VALUE commands,
1334 		 * and none of the VAR or VALUE commands are empty.
1335 		 * If the client has sent us a well-formed option,
1336 		 * then the number of VALUEs received should always
1337 		 * be less than or equal to the number of VARs and
1338 		 * USERVARs received.
1339 		 *
1340 		 * If we got exactly as many VALUEs as VARs and
1341 		 * USERVARs, the client has the same definitions.
1342 		 *
1343 		 * If we got exactly as many VARs as VALUEs and
1344 		 * USERVARS, the client has reversed definitions.
1345 		 */
1346 		if (got_uservar + got_var == got_value) {
1347 	    env_ovar_ok:
1348 			env_ovar = OLD_ENV_VAR;
1349 			env_ovalue = OLD_ENV_VALUE;
1350 		} else if (got_uservar + got_value == got_var) {
1351 	    env_ovar_wrong:
1352 			env_ovar = OLD_ENV_VALUE;
1353 			env_ovalue = OLD_ENV_VAR;
1354 			DIAG(TD_OPTIONS, {sprintf(nfrontp,
1355 				"ENVIRON VALUE and VAR are reversed!\r\n");
1356 				nfrontp += strlen(nfrontp);});
1357 
1358 		}
1359 	    }
1360 	    SB_RESTORE();
1361 #endif
1362 
1363 	    while (!SB_EOF()) {
1364 		c = SB_GET();
1365 		if ((c == env_ovar) || (c == ENV_USERVAR))
1366 			break;
1367 	    }
1368 	}
1369 
1370 	if (SB_EOF())
1371 		return;
1372 
1373 	cp = varp = (char *)subpointer;
1374 	valp = 0;
1375 
1376 	while (!SB_EOF()) {
1377 		c = SB_GET();
1378 		if (subchar == TELOPT_OLD_ENVIRON) {
1379 			if (c == env_ovar)
1380 				c = NEW_ENV_VAR;
1381 			else if (c == env_ovalue)
1382 				c = NEW_ENV_VALUE;
1383 		}
1384 		switch (c) {
1385 
1386 		case NEW_ENV_VALUE:
1387 			*cp = '\0';
1388 			cp = valp = (char *)subpointer;
1389 			break;
1390 
1391 		case NEW_ENV_VAR:
1392 		case ENV_USERVAR:
1393 			*cp = '\0';
1394 			if (valp)
1395 				(void)setenv(varp, valp, 1);
1396 			else
1397 				unsetenv(varp);
1398 			cp = varp = (char *)subpointer;
1399 			valp = 0;
1400 			break;
1401 
1402 		case ENV_ESC:
1403 			if (SB_EOF())
1404 				break;
1405 			c = SB_GET();
1406 			/* FALL THROUGH */
1407 		default:
1408 			*cp++ = c;
1409 			break;
1410 		}
1411 	}
1412 	*cp = '\0';
1413 	if (valp)
1414 		(void)setenv(varp, valp, 1);
1415 	else
1416 		unsetenv(varp);
1417 	break;
1418     }  /* end of case TELOPT_NEW_ENVIRON */
1419 #if	defined(AUTHENTICATION)
1420     case TELOPT_AUTHENTICATION:
1421 	if (SB_EOF())
1422 		break;
1423 	switch(SB_GET()) {
1424 	case TELQUAL_SEND:
1425 	case TELQUAL_REPLY:
1426 		/*
1427 		 * These are sent by us and cannot be sent by
1428 		 * the client.
1429 		 */
1430 		break;
1431 	case TELQUAL_IS:
1432 		auth_is(subpointer, SB_LEN());
1433 		break;
1434 	case TELQUAL_NAME:
1435 		auth_name(subpointer, SB_LEN());
1436 		break;
1437 	}
1438 	break;
1439 #endif
1440 #ifdef	ENCRYPTION
1441     case TELOPT_ENCRYPT:
1442 	if (SB_EOF())
1443 		break;
1444 	switch(SB_GET()) {
1445 	case ENCRYPT_SUPPORT:
1446 		encrypt_support(subpointer, SB_LEN());
1447 		break;
1448 	case ENCRYPT_IS:
1449 		encrypt_is(subpointer, SB_LEN());
1450 		break;
1451 	case ENCRYPT_REPLY:
1452 		encrypt_reply(subpointer, SB_LEN());
1453 		break;
1454 	case ENCRYPT_START:
1455 		encrypt_start(subpointer, SB_LEN());
1456 		break;
1457 	case ENCRYPT_END:
1458 		encrypt_end();
1459 		break;
1460 	case ENCRYPT_REQSTART:
1461 		encrypt_request_start(subpointer, SB_LEN());
1462 		break;
1463 	case ENCRYPT_REQEND:
1464 		/*
1465 		 * We can always send an REQEND so that we cannot
1466 		 * get stuck encrypting.  We should only get this
1467 		 * if we have been able to get in the correct mode
1468 		 * anyhow.
1469 		 */
1470 		encrypt_request_end();
1471 		break;
1472 	case ENCRYPT_ENC_KEYID:
1473 		encrypt_enc_keyid(subpointer, SB_LEN());
1474 		break;
1475 	case ENCRYPT_DEC_KEYID:
1476 		encrypt_dec_keyid(subpointer, SB_LEN());
1477 		break;
1478 	default:
1479 		break;
1480 	}
1481 	break;
1482 #endif	/* ENCRYPTION */
1483 
1484     default:
1485 	break;
1486     }  /* end of switch */
1487 
1488 }  /* end of suboption */
1489 
1490 	void
1491 doclientstat()
1492 {
1493 	clientstat(TELOPT_LINEMODE, WILL, 0);
1494 }
1495 
1496 #define	ADD(c)	 *ncp++ = c
1497 #define	ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; }
1498 	void
1499 send_status()
1500 {
1501 	unsigned char statusbuf[256];
1502 	register unsigned char *ncp;
1503 	register unsigned char i;
1504 
1505 	ncp = statusbuf;
1506 
1507 	netflush();	/* get rid of anything waiting to go out */
1508 
1509 	ADD(IAC);
1510 	ADD(SB);
1511 	ADD(TELOPT_STATUS);
1512 	ADD(TELQUAL_IS);
1513 
1514 	/*
1515 	 * We check the want_state rather than the current state,
1516 	 * because if we received a DO/WILL for an option that we
1517 	 * don't support, and the other side didn't send a DONT/WONT
1518 	 * in response to our WONT/DONT, then the "state" will be
1519 	 * WILL/DO, and the "want_state" will be WONT/DONT.  We
1520 	 * need to go by the latter.
1521 	 */
1522 	for (i = 0; i < (unsigned char)NTELOPTS; i++) {
1523 		if (my_want_state_is_will(i)) {
1524 			ADD(WILL);
1525 			ADD_DATA(i);
1526 		}
1527 		if (his_want_state_is_will(i)) {
1528 			ADD(DO);
1529 			ADD_DATA(i);
1530 		}
1531 	}
1532 
1533 	if (his_want_state_is_will(TELOPT_LFLOW)) {
1534 		ADD(SB);
1535 		ADD(TELOPT_LFLOW);
1536 		if (flowmode) {
1537 			ADD(LFLOW_ON);
1538 		} else {
1539 			ADD(LFLOW_OFF);
1540 		}
1541 		ADD(SE);
1542 
1543 		if (restartany >= 0) {
1544 			ADD(SB);
1545 			ADD(TELOPT_LFLOW);
1546 			if (restartany) {
1547 				ADD(LFLOW_RESTART_ANY);
1548 			} else {
1549 				ADD(LFLOW_RESTART_XON);
1550 			}
1551 			ADD(SE);
1552 		}
1553 	}
1554 
1555 #ifdef	LINEMODE
1556 	if (his_want_state_is_will(TELOPT_LINEMODE)) {
1557 		unsigned char *cp, *cpe;
1558 		int len;
1559 
1560 		ADD(SB);
1561 		ADD(TELOPT_LINEMODE);
1562 		ADD(LM_MODE);
1563 		ADD_DATA(editmode);
1564 		ADD(SE);
1565 
1566 		ADD(SB);
1567 		ADD(TELOPT_LINEMODE);
1568 		ADD(LM_SLC);
1569 		start_slc(0);
1570 		send_slc();
1571 		len = end_slc(&cp);
1572 		for (cpe = cp + len; cp < cpe; cp++)
1573 			ADD_DATA(*cp);
1574 		ADD(SE);
1575 	}
1576 #endif	/* LINEMODE */
1577 
1578 	ADD(IAC);
1579 	ADD(SE);
1580 
1581 	writenet(statusbuf, ncp - statusbuf);
1582 	netflush();	/* Send it on its way */
1583 
1584 	DIAG(TD_OPTIONS,
1585 		{printsub('>', statusbuf, ncp - statusbuf); netflush();});
1586 }
1587