xref: /original-bsd/libexec/telnetd/state.c (revision 2f219204)
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.3 (Berkeley) 02/16/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 			lmodetype = KLUDGE_LINEMODE;
694 # endif	/* KLUDGELINEMODE */
695 			clientstat(TELOPT_LINEMODE, WONT, 0);
696 			break;
697 #endif	/* LINEMODE */
698 
699 		case TELOPT_TM:
700 			/*
701 			 * If we get a WONT TM, and had sent a DO TM,
702 			 * don't respond with a DONT TM, just leave it
703 			 * as is.  Short circut the state machine to
704 			 * achive this.
705 			 */
706 			set_his_want_state_wont(TELOPT_TM);
707 			return;
708 
709 		case TELOPT_LFLOW:
710 			/*
711 			 * If we are not going to support flow control
712 			 * option, then let peer know that we can't
713 			 * change the flow control characters.
714 			 */
715 			slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
716 			slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
717 			slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
718 			slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
719 			break;
720 
721 #if	defined(AUTHENTICATION)
722 		case TELOPT_AUTHENTICATION:
723 			auth_finished(0, AUTH_REJECT);
724 			break;
725 #endif
726 
727 		/*
728 		 * For options that we might spin waiting for
729 		 * sub-negotiation, if the client turns off the
730 		 * option rather than responding to the request,
731 		 * we have to treat it here as if we got a response
732 		 * to the sub-negotiation, (by updating the timers)
733 		 * so that we'll break out of the loop.
734 		 */
735 		case TELOPT_TTYPE:
736 			settimer(ttypesubopt);
737 			break;
738 
739 		case TELOPT_TSPEED:
740 			settimer(tspeedsubopt);
741 			break;
742 
743 		case TELOPT_XDISPLOC:
744 			settimer(xdisplocsubopt);
745 			break;
746 
747 		case TELOPT_OLD_ENVIRON:
748 			settimer(oenvironsubopt);
749 			break;
750 
751 		case TELOPT_NEW_ENVIRON:
752 			settimer(environsubopt);
753 			break;
754 
755 		default:
756 			break;
757 		}
758 		set_his_want_state_wont(option);
759 		if (his_state_is_will(option))
760 			send_dont(option, 0);
761 	    } else {
762 		switch (option) {
763 		case TELOPT_TM:
764 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
765 			if (lmodetype < NO_AUTOKLUDGE) {
766 				lmodetype = NO_LINEMODE;
767 				clientstat(TELOPT_LINEMODE, WONT, 0);
768 				send_will(TELOPT_SGA, 1);
769 				send_will(TELOPT_ECHO, 1);
770 			}
771 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
772 			break;
773 
774 #if	defined(AUTHENTICATION)
775 		case TELOPT_AUTHENTICATION:
776 			auth_finished(0, AUTH_REJECT);
777 			break;
778 #endif
779 		default:
780 			break;
781 		}
782 	    }
783 	}
784 	set_his_state_wont(option);
785 
786 }  /* end of wontoption */
787 
788 	void
789 send_will(option, init)
790 	int option, init;
791 {
792 	if (init) {
793 		if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
794 		    my_want_state_is_will(option))
795 			return;
796 		set_my_want_state_will(option);
797 		will_wont_resp[option]++;
798 	}
799 	(void) sprintf(nfrontp, (char *)will, option);
800 	nfrontp += sizeof (doopt) - 2;
801 
802 	DIAG(TD_OPTIONS, printoption("td: send will", option));
803 }
804 
805 #if	!defined(LINEMODE) || !defined(KLUDGELINEMODE)
806 /*
807  * When we get a DONT SGA, we will try once to turn it
808  * back on.  If the other side responds DONT SGA, we
809  * leave it at that.  This is so that when we talk to
810  * clients that understand KLUDGELINEMODE but not LINEMODE,
811  * we'll keep them in char-at-a-time mode.
812  */
813 int turn_on_sga = 0;
814 #endif
815 
816 	void
817 dooption(option)
818 	int option;
819 {
820 	int changeok = 0;
821 
822 	/*
823 	 * Process client input.
824 	 */
825 
826 	DIAG(TD_OPTIONS, printoption("td: recv do", option));
827 
828 	if (will_wont_resp[option]) {
829 		will_wont_resp[option]--;
830 		if (will_wont_resp[option] && my_state_is_will(option))
831 			will_wont_resp[option]--;
832 	}
833 	if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
834 		switch (option) {
835 		case TELOPT_ECHO:
836 #ifdef	LINEMODE
837 # ifdef	KLUDGELINEMODE
838 			if (lmodetype == NO_LINEMODE)
839 # else
840 			if (his_state_is_wont(TELOPT_LINEMODE))
841 # endif
842 #endif
843 			{
844 				init_termbuf();
845 				tty_setecho(1);
846 				set_termbuf();
847 			}
848 			changeok++;
849 			break;
850 
851 		case TELOPT_BINARY:
852 			init_termbuf();
853 			tty_binaryout(1);
854 			set_termbuf();
855 			changeok++;
856 			break;
857 
858 		case TELOPT_SGA:
859 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
860 			/*
861 			 * If kludge linemode is in use, then we must
862 			 * process an incoming do SGA for linemode
863 			 * purposes.
864 			 */
865 			if (lmodetype == KLUDGE_LINEMODE) {
866 				/*
867 				 * Receipt of "do SGA" in kludge
868 				 * linemode is the peer asking us to
869 				 * turn off linemode.  Make note of
870 				 * the request.
871 				 */
872 				clientstat(TELOPT_LINEMODE, WONT, 0);
873 				/*
874 				 * If linemode did not get turned off
875 				 * then don't tell peer that we did.
876 				 * Breaking here forces a wont SGA to
877 				 * be returned.
878 				 */
879 				if (linemode)
880 					break;
881 			}
882 #else
883 			turn_on_sga = 0;
884 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
885 			changeok++;
886 			break;
887 
888 		case TELOPT_STATUS:
889 			changeok++;
890 			break;
891 
892 		case TELOPT_TM:
893 			/*
894 			 * Special case for TM.  We send a WILL, but
895 			 * pretend we sent a WONT.
896 			 */
897 			send_will(option, 0);
898 			set_my_want_state_wont(option);
899 			set_my_state_wont(option);
900 			return;
901 
902 		case TELOPT_LOGOUT:
903 			/*
904 			 * When we get a LOGOUT option, respond
905 			 * with a WILL LOGOUT, make sure that
906 			 * it gets written out to the network,
907 			 * and then just go away...
908 			 */
909 			set_my_want_state_will(TELOPT_LOGOUT);
910 			send_will(TELOPT_LOGOUT, 0);
911 			set_my_state_will(TELOPT_LOGOUT);
912 			(void)netflush();
913 			cleanup(0);
914 			/* NOT REACHED */
915 			break;
916 
917 #ifdef	ENCRYPTION
918 		case TELOPT_ENCRYPT:
919 			changeok++;
920 			break;
921 #endif	/* ENCRYPTION */
922 		case TELOPT_LINEMODE:
923 		case TELOPT_TTYPE:
924 		case TELOPT_NAWS:
925 		case TELOPT_TSPEED:
926 		case TELOPT_LFLOW:
927 		case TELOPT_XDISPLOC:
928 #ifdef	TELOPT_ENVIRON
929 		case TELOPT_NEW_ENVIRON:
930 #endif
931 		case TELOPT_OLD_ENVIRON:
932 		default:
933 			break;
934 		}
935 		if (changeok) {
936 			set_my_want_state_will(option);
937 			send_will(option, 0);
938 		} else {
939 			will_wont_resp[option]++;
940 			send_wont(option, 0);
941 		}
942 	}
943 	set_my_state_will(option);
944 
945 }  /* end of dooption */
946 
947 	void
948 send_wont(option, init)
949 	int option, init;
950 {
951 	if (init) {
952 		if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
953 		    my_want_state_is_wont(option))
954 			return;
955 		set_my_want_state_wont(option);
956 		will_wont_resp[option]++;
957 	}
958 	(void) sprintf(nfrontp, (char *)wont, option);
959 	nfrontp += sizeof (wont) - 2;
960 
961 	DIAG(TD_OPTIONS, printoption("td: send wont", option));
962 }
963 
964 	void
965 dontoption(option)
966 	int option;
967 {
968 	/*
969 	 * Process client input.
970 	 */
971 
972 
973 	DIAG(TD_OPTIONS, printoption("td: recv dont", option));
974 
975 	if (will_wont_resp[option]) {
976 		will_wont_resp[option]--;
977 		if (will_wont_resp[option] && my_state_is_wont(option))
978 			will_wont_resp[option]--;
979 	}
980 	if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
981 		switch (option) {
982 		case TELOPT_BINARY:
983 			init_termbuf();
984 			tty_binaryout(0);
985 			set_termbuf();
986 			break;
987 
988 		case TELOPT_ECHO:	/* we should stop echoing */
989 #ifdef	LINEMODE
990 # ifdef	KLUDGELINEMODE
991 			if ((lmodetype != REAL_LINEMODE) &&
992 			    (lmodetype != KLUDGE_LINEMODE))
993 # else
994 			if (his_state_is_wont(TELOPT_LINEMODE))
995 # endif
996 #endif
997 			{
998 				init_termbuf();
999 				tty_setecho(0);
1000 				set_termbuf();
1001 			}
1002 			break;
1003 
1004 		case TELOPT_SGA:
1005 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
1006 			/*
1007 			 * If kludge linemode is in use, then we
1008 			 * must process an incoming do SGA for
1009 			 * linemode purposes.
1010 			 */
1011 			if ((lmodetype == KLUDGE_LINEMODE) ||
1012 			    (lmodetype == KLUDGE_OK)) {
1013 				/*
1014 				 * The client is asking us to turn
1015 				 * linemode on.
1016 				 */
1017 				lmodetype = KLUDGE_LINEMODE;
1018 				clientstat(TELOPT_LINEMODE, WILL, 0);
1019 				/*
1020 				 * If we did not turn line mode on,
1021 				 * then what do we say?  Will SGA?
1022 				 * This violates design of telnet.
1023 				 * Gross.  Very Gross.
1024 				 */
1025 			}
1026 			break;
1027 #else
1028 			set_my_want_state_wont(option);
1029 			if (my_state_is_will(option))
1030 				send_wont(option, 0);
1031 			set_my_state_wont(option);
1032 			if (turn_on_sga ^= 1)
1033 				send_will(option, 1);
1034 			return;
1035 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
1036 
1037 		default:
1038 			break;
1039 		}
1040 
1041 		set_my_want_state_wont(option);
1042 		if (my_state_is_will(option))
1043 			send_wont(option, 0);
1044 	}
1045 	set_my_state_wont(option);
1046 
1047 }  /* end of dontoption */
1048 
1049 #ifdef	ENV_HACK
1050 int env_ovar = -1;
1051 int env_ovalue = -1;
1052 #else	/* ENV_HACK */
1053 # define env_ovar OLD_ENV_VAR
1054 # define env_ovalue OLD_ENV_VALUE
1055 #endif	/* ENV_HACK */
1056 
1057 /*
1058  * suboption()
1059  *
1060  *	Look at the sub-option buffer, and try to be helpful to the other
1061  * side.
1062  *
1063  *	Currently we recognize:
1064  *
1065  *	Terminal type is
1066  *	Linemode
1067  *	Window size
1068  *	Terminal speed
1069  */
1070 	void
1071 suboption()
1072 {
1073     register int subchar;
1074 
1075     DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
1076 
1077     subchar = SB_GET();
1078     switch (subchar) {
1079     case TELOPT_TSPEED: {
1080 	register int xspeed, rspeed;
1081 
1082 	if (his_state_is_wont(TELOPT_TSPEED))	/* Ignore if option disabled */
1083 		break;
1084 
1085 	settimer(tspeedsubopt);
1086 
1087 	if (SB_EOF() || SB_GET() != TELQUAL_IS)
1088 		return;
1089 
1090 	xspeed = atoi((char *)subpointer);
1091 
1092 	while (SB_GET() != ',' && !SB_EOF());
1093 	if (SB_EOF())
1094 		return;
1095 
1096 	rspeed = atoi((char *)subpointer);
1097 	clientstat(TELOPT_TSPEED, xspeed, rspeed);
1098 
1099 	break;
1100 
1101     }  /* end of case TELOPT_TSPEED */
1102 
1103     case TELOPT_TTYPE: {		/* Yaaaay! */
1104 	static char terminalname[41];
1105 
1106 	if (his_state_is_wont(TELOPT_TTYPE))	/* Ignore if option disabled */
1107 		break;
1108 	settimer(ttypesubopt);
1109 
1110 	if (SB_EOF() || SB_GET() != TELQUAL_IS) {
1111 	    return;		/* ??? XXX but, this is the most robust */
1112 	}
1113 
1114 	terminaltype = terminalname;
1115 
1116 	while ((terminaltype < (terminalname + sizeof terminalname-1)) &&
1117 								    !SB_EOF()) {
1118 	    register int c;
1119 
1120 	    c = SB_GET();
1121 	    if (isupper(c)) {
1122 		c = tolower(c);
1123 	    }
1124 	    *terminaltype++ = c;    /* accumulate name */
1125 	}
1126 	*terminaltype = 0;
1127 	terminaltype = terminalname;
1128 	break;
1129     }  /* end of case TELOPT_TTYPE */
1130 
1131     case TELOPT_NAWS: {
1132 	register int xwinsize, ywinsize;
1133 
1134 	if (his_state_is_wont(TELOPT_NAWS))	/* Ignore if option disabled */
1135 		break;
1136 
1137 	if (SB_EOF())
1138 		return;
1139 	xwinsize = SB_GET() << 8;
1140 	if (SB_EOF())
1141 		return;
1142 	xwinsize |= SB_GET();
1143 	if (SB_EOF())
1144 		return;
1145 	ywinsize = SB_GET() << 8;
1146 	if (SB_EOF())
1147 		return;
1148 	ywinsize |= SB_GET();
1149 	clientstat(TELOPT_NAWS, xwinsize, ywinsize);
1150 
1151 	break;
1152 
1153     }  /* end of case TELOPT_NAWS */
1154 
1155 #ifdef	LINEMODE
1156     case TELOPT_LINEMODE: {
1157 	register int request;
1158 
1159 	if (his_state_is_wont(TELOPT_LINEMODE))	/* Ignore if option disabled */
1160 		break;
1161 	/*
1162 	 * Process linemode suboptions.
1163 	 */
1164 	if (SB_EOF())
1165 	    break;		/* garbage was sent */
1166 	request = SB_GET();	/* get will/wont */
1167 
1168 	if (SB_EOF())
1169 	    break;		/* another garbage check */
1170 
1171 	if (request == LM_SLC) {  /* SLC is not preceeded by WILL or WONT */
1172 		/*
1173 		 * Process suboption buffer of slc's
1174 		 */
1175 		start_slc(1);
1176 		do_opt_slc(subpointer, subend - subpointer);
1177 		(void) end_slc(0);
1178 		break;
1179 	} else if (request == LM_MODE) {
1180 		if (SB_EOF())
1181 		    return;
1182 		useeditmode = SB_GET();  /* get mode flag */
1183 		clientstat(LM_MODE, 0, 0);
1184 		break;
1185 	}
1186 
1187 	if (SB_EOF())
1188 	    break;
1189 	switch (SB_GET()) {  /* what suboption? */
1190 	case LM_FORWARDMASK:
1191 		/*
1192 		 * According to spec, only server can send request for
1193 		 * forwardmask, and client can only return a positive response.
1194 		 * So don't worry about it.
1195 		 */
1196 
1197 	default:
1198 		break;
1199 	}
1200 	break;
1201     }  /* end of case TELOPT_LINEMODE */
1202 #endif
1203     case TELOPT_STATUS: {
1204 	int mode;
1205 
1206 	if (SB_EOF())
1207 	    break;
1208 	mode = SB_GET();
1209 	switch (mode) {
1210 	case TELQUAL_SEND:
1211 	    if (my_state_is_will(TELOPT_STATUS))
1212 		send_status();
1213 	    break;
1214 
1215 	case TELQUAL_IS:
1216 	    break;
1217 
1218 	default:
1219 	    break;
1220 	}
1221 	break;
1222     }  /* end of case TELOPT_STATUS */
1223 
1224     case TELOPT_XDISPLOC: {
1225 	if (SB_EOF() || SB_GET() != TELQUAL_IS)
1226 		return;
1227 	settimer(xdisplocsubopt);
1228 	subpointer[SB_LEN()] = '\0';
1229 	(void)setenv("DISPLAY", (char *)subpointer, 1);
1230 	break;
1231     }  /* end of case TELOPT_XDISPLOC */
1232 
1233 #ifdef	TELOPT_NEW_ENVIRON
1234     case TELOPT_NEW_ENVIRON:
1235 #endif
1236     case TELOPT_OLD_ENVIRON: {
1237 	register int c;
1238 	register char *cp, *varp, *valp;
1239 
1240 	if (SB_EOF())
1241 		return;
1242 	c = SB_GET();
1243 	if (c == TELQUAL_IS) {
1244 		if (subchar == TELOPT_OLD_ENVIRON)
1245 			settimer(oenvironsubopt);
1246 		else
1247 			settimer(environsubopt);
1248 	} else if (c != TELQUAL_INFO) {
1249 		return;
1250 	}
1251 
1252 #ifdef	TELOPT_NEW_ENVIRON
1253 	if (subchar == TELOPT_NEW_ENVIRON) {
1254 	    while (!SB_EOF()) {
1255 		c = SB_GET();
1256 		if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
1257 			break;
1258 	    }
1259 	} else
1260 #endif
1261 	{
1262 #ifdef	ENV_HACK
1263 	    /*
1264 	     * We only want to do this if we haven't already decided
1265 	     * whether or not the other side has its VALUE and VAR
1266 	     * reversed.
1267 	     */
1268 	    if (env_ovar < 0) {
1269 		register int last = -1;		/* invalid value */
1270 		int empty = 0;
1271 		int got_var = 0, got_value = 0, got_uservar = 0;
1272 
1273 		/*
1274 		 * The other side might have its VALUE and VAR values
1275 		 * reversed.  To be interoperable, we need to determine
1276 		 * which way it is.  If the first recognized character
1277 		 * is a VAR or VALUE, then that will tell us what
1278 		 * type of client it is.  If the fist recognized
1279 		 * character is a USERVAR, then we continue scanning
1280 		 * the suboption looking for two consecutive
1281 		 * VAR or VALUE fields.  We should not get two
1282 		 * consecutive VALUE fields, so finding two
1283 		 * consecutive VALUE or VAR fields will tell us
1284 		 * what the client is.
1285 		 */
1286 		SB_SAVE();
1287 		while (!SB_EOF()) {
1288 			c = SB_GET();
1289 			switch(c) {
1290 			case OLD_ENV_VAR:
1291 				if (last < 0 || last == OLD_ENV_VAR
1292 				    || (empty && (last == OLD_ENV_VALUE)))
1293 					goto env_ovar_ok;
1294 				got_var++;
1295 				last = OLD_ENV_VAR;
1296 				break;
1297 			case OLD_ENV_VALUE:
1298 				if (last < 0 || last == OLD_ENV_VALUE
1299 				    || (empty && (last == OLD_ENV_VAR)))
1300 					goto env_ovar_wrong;
1301 				got_value++;
1302 				last = OLD_ENV_VALUE;
1303 				break;
1304 			case ENV_USERVAR:
1305 				/* count strings of USERVAR as one */
1306 				if (last != ENV_USERVAR)
1307 					got_uservar++;
1308 				if (empty) {
1309 					if (last == OLD_ENV_VALUE)
1310 						goto env_ovar_ok;
1311 					if (last == OLD_ENV_VAR)
1312 						goto env_ovar_wrong;
1313 				}
1314 				last = ENV_USERVAR;
1315 				break;
1316 			case ENV_ESC:
1317 				if (!SB_EOF())
1318 					c = SB_GET();
1319 				/* FALL THROUGH */
1320 			default:
1321 				empty = 0;
1322 				continue;
1323 			}
1324 			empty = 1;
1325 		}
1326 		if (empty) {
1327 			if (last == OLD_ENV_VALUE)
1328 				goto env_ovar_ok;
1329 			if (last == OLD_ENV_VAR)
1330 				goto env_ovar_wrong;
1331 		}
1332 		/*
1333 		 * Ok, the first thing was a USERVAR, and there
1334 		 * are not two consecutive VAR or VALUE commands,
1335 		 * and none of the VAR or VALUE commands are empty.
1336 		 * If the client has sent us a well-formed option,
1337 		 * then the number of VALUEs received should always
1338 		 * be less than or equal to the number of VARs and
1339 		 * USERVARs received.
1340 		 *
1341 		 * If we got exactly as many VALUEs as VARs and
1342 		 * USERVARs, the client has the same definitions.
1343 		 *
1344 		 * If we got exactly as many VARs as VALUEs and
1345 		 * USERVARS, the client has reversed definitions.
1346 		 */
1347 		if (got_uservar + got_var == got_value) {
1348 	    env_ovar_ok:
1349 			env_ovar = OLD_ENV_VAR;
1350 			env_ovalue = OLD_ENV_VALUE;
1351 		} else if (got_uservar + got_value == got_var) {
1352 	    env_ovar_wrong:
1353 			env_ovar = OLD_ENV_VALUE;
1354 			env_ovalue = OLD_ENV_VAR;
1355 			DIAG(TD_OPTIONS, {sprintf(nfrontp,
1356 				"ENVIRON VALUE and VAR are reversed!\r\n");
1357 				nfrontp += strlen(nfrontp);});
1358 
1359 		}
1360 	    }
1361 	    SB_RESTORE();
1362 #endif
1363 
1364 	    while (!SB_EOF()) {
1365 		c = SB_GET();
1366 		if ((c == env_ovar) || (c == ENV_USERVAR))
1367 			break;
1368 	    }
1369 	}
1370 
1371 	if (SB_EOF())
1372 		return;
1373 
1374 	cp = varp = (char *)subpointer;
1375 	valp = 0;
1376 
1377 	while (!SB_EOF()) {
1378 		c = SB_GET();
1379 		if (subchar == TELOPT_OLD_ENVIRON) {
1380 			if (c == env_ovar)
1381 				c = NEW_ENV_VAR;
1382 			else if (c == env_ovalue)
1383 				c = NEW_ENV_VALUE;
1384 		}
1385 		switch (c) {
1386 
1387 		case NEW_ENV_VALUE:
1388 			*cp = '\0';
1389 			cp = valp = (char *)subpointer;
1390 			break;
1391 
1392 		case NEW_ENV_VAR:
1393 		case ENV_USERVAR:
1394 			*cp = '\0';
1395 			if (valp)
1396 				(void)setenv(varp, valp, 1);
1397 			else
1398 				unsetenv(varp);
1399 			cp = varp = (char *)subpointer;
1400 			valp = 0;
1401 			break;
1402 
1403 		case ENV_ESC:
1404 			if (SB_EOF())
1405 				break;
1406 			c = SB_GET();
1407 			/* FALL THROUGH */
1408 		default:
1409 			*cp++ = c;
1410 			break;
1411 		}
1412 	}
1413 	*cp = '\0';
1414 	if (valp)
1415 		(void)setenv(varp, valp, 1);
1416 	else
1417 		unsetenv(varp);
1418 	break;
1419     }  /* end of case TELOPT_NEW_ENVIRON */
1420 #if	defined(AUTHENTICATION)
1421     case TELOPT_AUTHENTICATION:
1422 	if (SB_EOF())
1423 		break;
1424 	switch(SB_GET()) {
1425 	case TELQUAL_SEND:
1426 	case TELQUAL_REPLY:
1427 		/*
1428 		 * These are sent by us and cannot be sent by
1429 		 * the client.
1430 		 */
1431 		break;
1432 	case TELQUAL_IS:
1433 		auth_is(subpointer, SB_LEN());
1434 		break;
1435 	case TELQUAL_NAME:
1436 		auth_name(subpointer, SB_LEN());
1437 		break;
1438 	}
1439 	break;
1440 #endif
1441 #ifdef	ENCRYPTION
1442     case TELOPT_ENCRYPT:
1443 	if (SB_EOF())
1444 		break;
1445 	switch(SB_GET()) {
1446 	case ENCRYPT_SUPPORT:
1447 		encrypt_support(subpointer, SB_LEN());
1448 		break;
1449 	case ENCRYPT_IS:
1450 		encrypt_is(subpointer, SB_LEN());
1451 		break;
1452 	case ENCRYPT_REPLY:
1453 		encrypt_reply(subpointer, SB_LEN());
1454 		break;
1455 	case ENCRYPT_START:
1456 		encrypt_start(subpointer, SB_LEN());
1457 		break;
1458 	case ENCRYPT_END:
1459 		encrypt_end();
1460 		break;
1461 	case ENCRYPT_REQSTART:
1462 		encrypt_request_start(subpointer, SB_LEN());
1463 		break;
1464 	case ENCRYPT_REQEND:
1465 		/*
1466 		 * We can always send an REQEND so that we cannot
1467 		 * get stuck encrypting.  We should only get this
1468 		 * if we have been able to get in the correct mode
1469 		 * anyhow.
1470 		 */
1471 		encrypt_request_end();
1472 		break;
1473 	case ENCRYPT_ENC_KEYID:
1474 		encrypt_enc_keyid(subpointer, SB_LEN());
1475 		break;
1476 	case ENCRYPT_DEC_KEYID:
1477 		encrypt_dec_keyid(subpointer, SB_LEN());
1478 		break;
1479 	default:
1480 		break;
1481 	}
1482 	break;
1483 #endif	/* ENCRYPTION */
1484 
1485     default:
1486 	break;
1487     }  /* end of switch */
1488 
1489 }  /* end of suboption */
1490 
1491 	void
1492 doclientstat()
1493 {
1494 	clientstat(TELOPT_LINEMODE, WILL, 0);
1495 }
1496 
1497 #define	ADD(c)	 *ncp++ = c
1498 #define	ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; }
1499 	void
1500 send_status()
1501 {
1502 	unsigned char statusbuf[256];
1503 	register unsigned char *ncp;
1504 	register unsigned char i;
1505 
1506 	ncp = statusbuf;
1507 
1508 	netflush();	/* get rid of anything waiting to go out */
1509 
1510 	ADD(IAC);
1511 	ADD(SB);
1512 	ADD(TELOPT_STATUS);
1513 	ADD(TELQUAL_IS);
1514 
1515 	/*
1516 	 * We check the want_state rather than the current state,
1517 	 * because if we received a DO/WILL for an option that we
1518 	 * don't support, and the other side didn't send a DONT/WONT
1519 	 * in response to our WONT/DONT, then the "state" will be
1520 	 * WILL/DO, and the "want_state" will be WONT/DONT.  We
1521 	 * need to go by the latter.
1522 	 */
1523 	for (i = 0; i < (unsigned char)NTELOPTS; i++) {
1524 		if (my_want_state_is_will(i)) {
1525 			ADD(WILL);
1526 			ADD_DATA(i);
1527 		}
1528 		if (his_want_state_is_will(i)) {
1529 			ADD(DO);
1530 			ADD_DATA(i);
1531 		}
1532 	}
1533 
1534 	if (his_want_state_is_will(TELOPT_LFLOW)) {
1535 		ADD(SB);
1536 		ADD(TELOPT_LFLOW);
1537 		if (flowmode) {
1538 			ADD(LFLOW_ON);
1539 		} else {
1540 			ADD(LFLOW_OFF);
1541 		}
1542 		ADD(SE);
1543 
1544 		if (restartany >= 0) {
1545 			ADD(SB);
1546 			ADD(TELOPT_LFLOW);
1547 			if (restartany) {
1548 				ADD(LFLOW_RESTART_ANY);
1549 			} else {
1550 				ADD(LFLOW_RESTART_XON);
1551 			}
1552 			ADD(SE);
1553 		}
1554 	}
1555 
1556 #ifdef	LINEMODE
1557 	if (his_want_state_is_will(TELOPT_LINEMODE)) {
1558 		unsigned char *cp, *cpe;
1559 		int len;
1560 
1561 		ADD(SB);
1562 		ADD(TELOPT_LINEMODE);
1563 		ADD(LM_MODE);
1564 		ADD_DATA(editmode);
1565 		ADD(SE);
1566 
1567 		ADD(SB);
1568 		ADD(TELOPT_LINEMODE);
1569 		ADD(LM_SLC);
1570 		start_slc(0);
1571 		send_slc();
1572 		len = end_slc(&cp);
1573 		for (cpe = cp + len; cp < cpe; cp++)
1574 			ADD_DATA(*cp);
1575 		ADD(SE);
1576 	}
1577 #endif	/* LINEMODE */
1578 
1579 	ADD(IAC);
1580 	ADD(SE);
1581 
1582 	writenet(statusbuf, ncp - statusbuf);
1583 	netflush();	/* Send it on its way */
1584 
1585 	DIAG(TD_OPTIONS,
1586 		{printsub('>', statusbuf, ncp - statusbuf); netflush();});
1587 }
1588