1/*	$NetBSD: state.c,v 1.34 2024/02/10 09:21:52 andvar Exp $	*/
2
3/*
4 * Copyright (c) 1989, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33#ifndef lint
34#if 0
35static char sccsid[] = "@(#)state.c	8.5 (Berkeley) 5/30/95";
36#else
37__RCSID("$NetBSD: state.c,v 1.34 2024/02/10 09:21:52 andvar Exp $");
38#endif
39#endif /* not lint */
40
41#include <ctype.h>
42#include <stdarg.h>
43
44#include "telnetd.h"
45
46static int envvarok(char *);
47
48int	not42 = 1;
49
50/*
51 * Buffer for sub-options, and macros
52 * for suboptions buffer manipulations
53 */
54unsigned char subbuffer[4096], *subpointer= subbuffer, *subend= subbuffer;
55
56#define	SB_CLEAR()	subpointer = subbuffer
57#define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
58#define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \
59				*subpointer++ = (c); \
60			}
61#define	SB_GET()	((*subpointer++)&0xff)
62#define	SB_EOF()	(subpointer >= subend)
63#define	SB_LEN()	(subend - subpointer)
64
65#ifdef	ENV_HACK
66unsigned char *subsave;
67#define SB_SAVE()	subsave = subpointer;
68#define	SB_RESTORE()	subpointer = subsave;
69#endif
70
71
72/*
73 * State for recv fsm
74 */
75#define	TS_DATA		0	/* base state */
76#define	TS_IAC		1	/* look for double IAC's */
77#define	TS_CR		2	/* CR-LF ->'s CR */
78#define	TS_SB		3	/* throw away begin's... */
79#define	TS_SE		4	/* ...end's (suboption negotiation) */
80#define	TS_WILL		5	/* will option negotiation */
81#define	TS_WONT		6	/* wont " */
82#define	TS_DO		7	/* do " */
83#define	TS_DONT		8	/* dont " */
84
85void
86telrcv(void)
87{
88	int c;
89	static int state = TS_DATA;
90
91	while (ncc > 0) {
92		if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
93			break;
94		c = *netip++ & 0377, ncc--;
95#ifdef	ENCRYPTION
96		if (decrypt_input)
97			c = (*decrypt_input)(c);
98#endif	/* ENCRYPTION */
99		switch (state) {
100
101		case TS_CR:
102			state = TS_DATA;
103
104#ifdef	LINEMODE
105			/*
106			 * If we are operating in linemode,
107			 * convert to local end-of-line.
108			 */
109			if (linemode && (ncc > 0) && ((c == '\n') ||
110				 ((c == 0) && tty_iscrnl())) )
111				c = '\n';
112			else
113#endif
114			{
115				/*
116				 * We now map \r\n ==> \r for pragmatic reasons.
117				 * Many client implementations send \r\n when
118				 * the user hits the CarriageReturn key.
119				 *
120				 * We USED to map \r\n ==> \n, since \r\n says
121				 * that we want to be in column 1 of the next
122				 * printable line, and \n is the standard
123				 * unix way of saying that (\r is only good
124				 * if CRMOD is set, which it normally is).
125				 */
126
127				/* Strip off \n or \0 after a \r */
128				if ((c == 0) || (c == '\n'))
129					break;
130			}
131			/* FALL THROUGH */
132
133		case TS_DATA:
134			if (c == IAC) {
135				state = TS_IAC;
136				break;
137			}
138
139			if ((c == '\r') && his_state_is_wont(TELOPT_BINARY))
140				state = TS_CR;
141
142			*pfrontp++ = c;
143			break;
144
145		case TS_IAC:
146gotiac:			switch (c) {
147
148			/*
149			 * Send the process on the pty side an
150			 * interrupt.  Do this with a NULL or
151			 * interrupt char; depending on the tty mode.
152			 */
153			case IP:
154				DIAG(TD_OPTIONS,
155					printoption("td: recv IAC", c));
156				interrupt();
157				break;
158
159			case BREAK:
160				DIAG(TD_OPTIONS,
161					printoption("td: recv IAC", c));
162				sendbrk();
163				break;
164
165			/*
166			 * Are You There?
167			 */
168			case AYT:
169				DIAG(TD_OPTIONS,
170					printoption("td: recv IAC", c));
171				recv_ayt();
172				break;
173
174			/*
175			 * Abort Output
176			 */
177			case AO:
178			    {
179				DIAG(TD_OPTIONS,
180					printoption("td: recv IAC", c));
181				ptyflush();	/* half-hearted */
182				init_termbuf();
183
184				if (slctab[SLC_AO].sptr &&
185				    *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
186				    *pfrontp++ =
187					(unsigned char)*slctab[SLC_AO].sptr;
188				}
189
190				netclear();	/* clear buffer back */
191				output_data("%c%c", IAC, DM);
192				neturg = nfrontp - 1; /* off by one XXX */
193				DIAG(TD_OPTIONS,
194					printoption("td: send IAC", DM));
195				break;
196			    }
197
198			/*
199			 * Erase Character and
200			 * Erase Line
201			 */
202			case EC:
203			case EL:
204			    {
205				cc_t ch;
206
207				DIAG(TD_OPTIONS,
208					printoption("td: recv IAC", c));
209				ptyflush();	/* half-hearted */
210				init_termbuf();
211				if (c == EC)
212					ch = *slctab[SLC_EC].sptr;
213				else
214					ch = *slctab[SLC_EL].sptr;
215				if (ch != (cc_t)(_POSIX_VDISABLE))
216					*pfrontp++ = (unsigned char)ch;
217				break;
218			    }
219
220			/*
221			 * Check for urgent data...
222			 */
223			case DM:
224				DIAG(TD_OPTIONS,
225					printoption("td: recv IAC", c));
226				SYNCHing = stilloob(net);
227				settimer(gotDM);
228				break;
229
230
231			/*
232			 * Begin option subnegotiation...
233			 */
234			case SB:
235				state = TS_SB;
236				SB_CLEAR();
237				continue;
238
239			case WILL:
240				state = TS_WILL;
241				continue;
242
243			case WONT:
244				state = TS_WONT;
245				continue;
246
247			case DO:
248				state = TS_DO;
249				continue;
250
251			case DONT:
252				state = TS_DONT;
253				continue;
254			case EOR:
255				if (his_state_is_will(TELOPT_EOR))
256					doeof();
257				break;
258
259			/*
260			 * Handle RFC 10xx Telnet linemode option additions
261			 * to command stream (EOF, SUSP, ABORT).
262			 */
263			case xEOF:
264				doeof();
265				break;
266
267			case SUSP:
268				sendsusp();
269				break;
270
271			case ABORT:
272				sendbrk();
273				break;
274
275			case IAC:
276				*pfrontp++ = c;
277				break;
278			}
279			state = TS_DATA;
280			break;
281
282		case TS_SB:
283			if (c == IAC) {
284				state = TS_SE;
285			} else {
286				SB_ACCUM(c);
287			}
288			break;
289
290		case TS_SE:
291			if (c != SE) {
292				if (c != IAC) {
293					/*
294					 * bad form of suboption negotiation.
295					 * handle it in such a way as to avoid
296					 * damage to local state.  Parse
297					 * suboption buffer found so far,
298					 * then treat remaining stream as
299					 * another command sequence.
300					 */
301
302					/* for DIAGNOSTICS */
303					SB_ACCUM(IAC);
304					SB_ACCUM(c);
305					subpointer -= 2;
306
307					SB_TERM();
308					suboption();
309					state = TS_IAC;
310					goto gotiac;
311				}
312				SB_ACCUM(c);
313				state = TS_SB;
314			} else {
315				/* for DIAGNOSTICS */
316				SB_ACCUM(IAC);
317				SB_ACCUM(SE);
318				subpointer -= 2;
319
320				SB_TERM();
321				suboption();	/* handle sub-option */
322				state = TS_DATA;
323			}
324			break;
325
326		case TS_WILL:
327			willoption(c);
328			state = TS_DATA;
329			continue;
330
331		case TS_WONT:
332			wontoption(c);
333			state = TS_DATA;
334			continue;
335
336		case TS_DO:
337			dooption(c);
338			state = TS_DATA;
339			continue;
340
341		case TS_DONT:
342			dontoption(c);
343			state = TS_DATA;
344			continue;
345
346		default:
347			syslog(LOG_ERR, "panic state=%d", state);
348			printf("telnetd: panic state=%d\n", state);
349			exit(1);
350		}
351	}
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 * acknowledgment 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 acknowledgment 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 */
410void
411send_do(int option, int init)
412{
413	if (init) {
414		if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
415		    his_want_state_is_will(option))
416			return;
417		/*
418		 * Special case for TELOPT_TM:  We send a DO, but pretend
419		 * that we sent a DONT, so that we can send more DOs if
420		 * we want to.
421		 */
422		if (option == TELOPT_TM)
423			set_his_want_state_wont(option);
424		else
425			set_his_want_state_will(option);
426		do_dont_resp[option]++;
427	}
428	(void) output_data("%c%c%c", IAC, DO, option);
429
430	DIAG(TD_OPTIONS, printoption("td: send do", option));
431}
432
433#ifdef	LINEMODE
434extern void doclientstat(void);
435#endif
436#if 0
437#ifdef	AUTHENTICATION
438extern void auth_request(void);	/* libtelnet */
439#endif
440#ifdef	ENCRYPTION
441extern void encrypt_send_support(void);
442#endif	/* ENCRYPTION */
443#endif
444
445void
446willoption(int option)
447{
448	int changeok = 0;
449	void (*func)(void) = 0;
450
451	/*
452	 * process input from peer.
453	 */
454
455	DIAG(TD_OPTIONS, printoption("td: recv will", option));
456
457	if (do_dont_resp[option]) {
458		do_dont_resp[option]--;
459		if (do_dont_resp[option] && his_state_is_will(option))
460			do_dont_resp[option]--;
461	}
462	if (do_dont_resp[option] == 0) {
463	    if (his_want_state_is_wont(option)) {
464		switch (option) {
465
466		case TELOPT_BINARY:
467			init_termbuf();
468			tty_binaryin(1);
469			set_termbuf();
470			changeok++;
471			break;
472
473		case TELOPT_ECHO:
474			/*
475			 * See comments below for more info.
476			 */
477			not42 = 0;	/* looks like a 4.2 system */
478			break;
479
480		case TELOPT_TM:
481#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
482			/*
483			 * This telnetd implementation does not really
484			 * support timing marks, it just uses them to
485			 * support the kludge linemode stuff.  If we
486			 * receive a will or wont TM in response to our
487			 * do TM request that may have been sent to
488			 * determine kludge linemode support, process
489			 * it, otherwise TM should get a negative
490			 * response back.
491			 */
492			/*
493			 * Handle the linemode kludge stuff.
494			 * If we are not currently supporting any
495			 * linemode at all, then we assume that this
496			 * is the client telling us to use kludge
497			 * linemode in response to our query.  Set the
498			 * linemode type that is to be supported, note
499			 * that the client wishes to use linemode, and
500			 * eat the will TM as though it never arrived.
501			 */
502			if (lmodetype < KLUDGE_LINEMODE) {
503				lmodetype = KLUDGE_LINEMODE;
504				clientstat(TELOPT_LINEMODE, WILL, 0);
505				send_wont(TELOPT_SGA, 1);
506			} else if (lmodetype == NO_AUTOKLUDGE) {
507				lmodetype = KLUDGE_OK;
508			}
509#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
510			/*
511			 * We never respond to a WILL TM, and
512			 * we leave the state WONT.
513			 */
514			return;
515
516		case TELOPT_LFLOW:
517			/*
518			 * If we are going to support flow control
519			 * option, then don't worry peer that we can't
520			 * change the flow control characters.
521			 */
522			slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
523			slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
524			slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
525			slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
526			/* FALLTHROUGH */
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 propagated 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
628		case TELOPT_LFLOW:
629			func = flowstat;
630			break;
631		}
632	    }
633	}
634	set_his_state_will(option);
635	if (func)
636		(*func)();
637}  /* end of willoption */
638
639void
640send_dont(int option, int 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) output_data("%c%c%c", IAC, DONT, option);
650
651	DIAG(TD_OPTIONS, printoption("td: send dont", option));
652}
653
654void
655wontoption(int option)
656{
657	/*
658	 * Process client input.
659	 */
660
661	DIAG(TD_OPTIONS, printoption("td: recv wont", option));
662
663	if (do_dont_resp[option]) {
664		do_dont_resp[option]--;
665		if (do_dont_resp[option] && his_state_is_wont(option))
666			do_dont_resp[option]--;
667	}
668	if (do_dont_resp[option] == 0) {
669	    if (his_want_state_is_will(option)) {
670		/* it is always ok to change to negative state */
671		switch (option) {
672		case TELOPT_ECHO:
673			not42 = 1; /* doesn't seem to be a 4.2 system */
674			break;
675
676		case TELOPT_BINARY:
677			init_termbuf();
678			tty_binaryin(0);
679			set_termbuf();
680			break;
681
682#ifdef	LINEMODE
683		case TELOPT_LINEMODE:
684# ifdef	KLUDGELINEMODE
685			/*
686			 * If real linemode is supported, then client is
687			 * asking to turn linemode off.
688			 */
689			if (lmodetype != REAL_LINEMODE)
690				break;
691			/* XXX double-check this --thorpej */
692			lmodetype = KLUDGE_LINEMODE;
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			 * achieve 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#ifdef 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#ifdef 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
787void
788send_will(int option, int init)
789{
790	if (init) {
791		if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
792		    my_want_state_is_will(option))
793			return;
794		set_my_want_state_will(option);
795		will_wont_resp[option]++;
796	}
797	(void) output_data("%c%c%c", IAC, WILL, option);
798
799	DIAG(TD_OPTIONS, printoption("td: send will", option));
800}
801
802#if	!defined(LINEMODE) || !defined(KLUDGELINEMODE)
803/*
804 * When we get a DONT SGA, we will try once to turn it
805 * back on.  If the other side responds DONT SGA, we
806 * leave it at that.  This is so that when we talk to
807 * clients that understand KLUDGELINEMODE but not LINEMODE,
808 * we'll keep them in char-at-a-time mode.
809 */
810int turn_on_sga = 0;
811#endif
812
813void
814dooption(int option)
815{
816	int changeok = 0;
817
818	/*
819	 * Process client input.
820	 */
821
822	DIAG(TD_OPTIONS, printoption("td: recv do", option));
823
824	if (will_wont_resp[option]) {
825		will_wont_resp[option]--;
826		if (will_wont_resp[option] && my_state_is_will(option))
827			will_wont_resp[option]--;
828	}
829	if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
830		switch (option) {
831		case TELOPT_ECHO:
832#ifdef	LINEMODE
833# ifdef	KLUDGELINEMODE
834			if (lmodetype == NO_LINEMODE)
835# else
836			if (his_state_is_wont(TELOPT_LINEMODE))
837# endif
838#endif
839			{
840				init_termbuf();
841				tty_setecho(1);
842				set_termbuf();
843			}
844			changeok++;
845			break;
846
847		case TELOPT_BINARY:
848			init_termbuf();
849			tty_binaryout(1);
850			set_termbuf();
851			changeok++;
852			break;
853
854		case TELOPT_SGA:
855#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
856			/*
857			 * If kludge linemode is in use, then we must
858			 * process an incoming do SGA for linemode
859			 * purposes.
860			 */
861			if (lmodetype == KLUDGE_LINEMODE) {
862				/*
863				 * Receipt of "do SGA" in kludge
864				 * linemode is the peer asking us to
865				 * turn off linemode.  Make note of
866				 * the request.
867				 */
868				clientstat(TELOPT_LINEMODE, WONT, 0);
869				/*
870				 * If linemode did not get turned off
871				 * then don't tell peer that we did.
872				 * Breaking here forces a wont SGA to
873				 * be returned.
874				 */
875				if (linemode)
876					break;
877			}
878#else
879			turn_on_sga = 0;
880#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
881			changeok++;
882			break;
883
884		case TELOPT_STATUS:
885			changeok++;
886			break;
887
888		case TELOPT_TM:
889			/*
890			 * Special case for TM.  We send a WILL, but
891			 * pretend we sent a WONT.
892			 */
893			send_will(option, 0);
894			set_my_want_state_wont(option);
895			set_my_state_wont(option);
896			return;
897
898		case TELOPT_LOGOUT:
899			/*
900			 * When we get a LOGOUT option, respond
901			 * with a WILL LOGOUT, make sure that
902			 * it gets written out to the network,
903			 * and then just go away...
904			 */
905			set_my_want_state_will(TELOPT_LOGOUT);
906			send_will(TELOPT_LOGOUT, 0);
907			set_my_state_will(TELOPT_LOGOUT);
908			(void)netflush();
909			cleanup(0);
910			/* NOT REACHED */
911			break;
912
913#ifdef	ENCRYPTION
914		case TELOPT_ENCRYPT:
915			changeok++;
916			break;
917#endif	/* ENCRYPTION */
918
919		case TELOPT_LINEMODE:
920		case TELOPT_TTYPE:
921		case TELOPT_NAWS:
922		case TELOPT_TSPEED:
923		case TELOPT_LFLOW:
924		case TELOPT_XDISPLOC:
925		case TELOPT_OLD_ENVIRON:
926		default:
927			break;
928		}
929		if (changeok) {
930			set_my_want_state_will(option);
931			send_will(option, 0);
932		} else {
933			will_wont_resp[option]++;
934			send_wont(option, 0);
935		}
936	}
937	set_my_state_will(option);
938
939}  /* end of dooption */
940
941void
942send_wont(int option, int init)
943{
944	if (init) {
945		if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
946		    my_want_state_is_wont(option))
947			return;
948		set_my_want_state_wont(option);
949		will_wont_resp[option]++;
950	}
951	(void) output_data("%c%c%c", IAC, WONT, option);
952
953	DIAG(TD_OPTIONS, printoption("td: send wont", option));
954}
955
956void
957dontoption(int option)
958{
959	/*
960	 * Process client input.
961	 */
962
963
964	DIAG(TD_OPTIONS, printoption("td: recv dont", option));
965
966	if (will_wont_resp[option]) {
967		will_wont_resp[option]--;
968		if (will_wont_resp[option] && my_state_is_wont(option))
969			will_wont_resp[option]--;
970	}
971	if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
972		switch (option) {
973		case TELOPT_BINARY:
974			init_termbuf();
975			tty_binaryout(0);
976			set_termbuf();
977			break;
978
979		case TELOPT_ECHO:	/* we should stop echoing */
980#ifdef	LINEMODE
981# ifdef	KLUDGELINEMODE
982			if ((lmodetype != REAL_LINEMODE) &&
983			    (lmodetype != KLUDGE_LINEMODE))
984# else
985			if (his_state_is_wont(TELOPT_LINEMODE))
986# endif
987#endif
988			{
989				init_termbuf();
990				tty_setecho(0);
991				set_termbuf();
992			}
993			break;
994
995		case TELOPT_SGA:
996#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
997			/*
998			 * If kludge linemode is in use, then we
999			 * must process an incoming do SGA for
1000			 * linemode purposes.
1001			 */
1002			if ((lmodetype == KLUDGE_LINEMODE) ||
1003			    (lmodetype == KLUDGE_OK)) {
1004				/*
1005				 * The client is asking us to turn
1006				 * linemode on.
1007				 */
1008				lmodetype = KLUDGE_LINEMODE;
1009				clientstat(TELOPT_LINEMODE, WILL, 0);
1010				/*
1011				 * If we did not turn line mode on,
1012				 * then what do we say?  Will SGA?
1013				 * This violates design of telnet.
1014				 * Gross.  Very Gross.
1015				 */
1016			}
1017			break;
1018#else
1019			set_my_want_state_wont(option);
1020			if (my_state_is_will(option))
1021				send_wont(option, 0);
1022			set_my_state_wont(option);
1023			if (turn_on_sga ^= 1)
1024				send_will(option, 1);
1025			return;
1026#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
1027
1028		default:
1029			break;
1030		}
1031
1032		set_my_want_state_wont(option);
1033		if (my_state_is_will(option))
1034			send_wont(option, 0);
1035	}
1036	set_my_state_wont(option);
1037
1038}  /* end of dontoption */
1039
1040#ifdef	ENV_HACK
1041int env_ovar = -1;
1042int env_ovalue = -1;
1043#else	/* ENV_HACK */
1044# define env_ovar OLD_ENV_VAR
1045# define env_ovalue OLD_ENV_VALUE
1046#endif	/* ENV_HACK */
1047
1048/* envvarok(char*) */
1049/* check that variable is safe to pass to login or shell */
1050static int
1051envvarok(char *varp)
1052{
1053
1054	if (strcmp(varp, "TERMCAP") &&	/* to prevent a security hole */
1055	    strcmp(varp, "TERMINFO") &&	/* with tgetent */
1056	    strcmp(varp, "TERMPATH") &&
1057	    strcmp(varp, "HOME") &&	/* to prevent the tegetent bug  */
1058	    strncmp(varp, "LD_", strlen("LD_")) &&	/* most systems */
1059	    strncmp(varp, "_RLD_", strlen("_RLD_")) &&	/* IRIX */
1060	    strcmp(varp, "LIBPATH") &&			/* AIX */
1061	    strcmp(varp, "ENV") &&
1062	    strcmp(varp, "BASH_ENV") &&
1063	    strcmp(varp, "IFS") &&
1064	    strncmp(varp, "KRB5", strlen("KRB5")) &&	/* Krb5 */
1065	    /*
1066	     * The above case is a catch-all for now.  Here are some of
1067	     * the specific ones we must avoid passing, at least until
1068	     * we can prove it can be done safely.  Keep this list
1069	     * around un case someone wants to remove the catch-all.
1070	     */
1071	    strcmp(varp, "KRB5_CONFIG") &&		/* Krb5 */
1072	    strcmp(varp, "KRB5CCNAME") &&		/* Krb5 */
1073	    strcmp(varp, "KRB5_KTNAME") &&		/* Krb5 */
1074	    strcmp(varp, "KRBTKFILE") &&		/* Krb4 */
1075	    strcmp(varp, "KRB_CONF") &&			/* CNS 4 */
1076	    strcmp(varp, "KRB_REALMS") &&		/* CNS 4 */
1077	    strcmp(varp, "RESOLV_HOST_CONF"))		/* Linux */
1078		return (1);
1079	else {
1080		syslog(LOG_INFO, "Rejected the attempt to modify the "
1081		    "environment variable \"%s\"", varp);
1082		return (0);
1083	}
1084}
1085
1086/*
1087 * suboption()
1088 *
1089 *	Look at the sub-option buffer, and try to be helpful to the other
1090 * side.
1091 *
1092 *	Currently we recognize:
1093 *
1094 *	Terminal type is
1095 *	Linemode
1096 *	Window size
1097 *	Terminal speed
1098 */
1099void
1100suboption(void)
1101{
1102    int subchar;
1103
1104    DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
1105
1106    subchar = SB_GET();
1107    switch (subchar) {
1108    case TELOPT_TSPEED: {
1109	int xspeed, rspeed;
1110
1111	if (his_state_is_wont(TELOPT_TSPEED))	/* Ignore if option disabled */
1112		break;
1113
1114	settimer(tspeedsubopt);
1115
1116	if (SB_EOF() || SB_GET() != TELQUAL_IS)
1117		return;
1118
1119	xspeed = atoi((char *)subpointer);
1120
1121	while (SB_GET() != ',' && !SB_EOF());
1122	if (SB_EOF())
1123		return;
1124
1125	rspeed = atoi((char *)subpointer);
1126	clientstat(TELOPT_TSPEED, xspeed, rspeed);
1127
1128	break;
1129
1130    }  /* end of case TELOPT_TSPEED */
1131
1132    case TELOPT_TTYPE: {		/* Yaaaay! */
1133	char *p;
1134
1135	if (his_state_is_wont(TELOPT_TTYPE))	/* Ignore if option disabled */
1136		break;
1137	settimer(ttypesubopt);
1138
1139	if (SB_EOF() || SB_GET() != TELQUAL_IS) {
1140	    return;		/* ??? XXX but, this is the most robust */
1141	}
1142
1143	p = terminaltype;
1144
1145	while ((p < (terminaltype + sizeof terminaltype-1)) &&
1146								    !SB_EOF()) {
1147	    int c;
1148
1149	    c = SB_GET();
1150	    if (isupper(c)) {
1151		c = tolower(c);
1152	    }
1153	    *p++ = c;    /* accumulate name */
1154	}
1155	*p = 0;
1156	break;
1157    }  /* end of case TELOPT_TTYPE */
1158
1159    case TELOPT_NAWS: {
1160	int xwinsize, ywinsize;
1161
1162	if (his_state_is_wont(TELOPT_NAWS))	/* Ignore if option disabled */
1163		break;
1164
1165	if (SB_EOF())
1166		return;
1167	xwinsize = SB_GET() << 8;
1168	if (SB_EOF())
1169		return;
1170	xwinsize |= SB_GET();
1171	if (SB_EOF())
1172		return;
1173	ywinsize = SB_GET() << 8;
1174	if (SB_EOF())
1175		return;
1176	ywinsize |= SB_GET();
1177	clientstat(TELOPT_NAWS, xwinsize, ywinsize);
1178
1179	break;
1180
1181    }  /* end of case TELOPT_NAWS */
1182
1183#ifdef	LINEMODE
1184    case TELOPT_LINEMODE: {
1185	int request;
1186
1187	if (his_state_is_wont(TELOPT_LINEMODE))	/* Ignore if option disabled */
1188		break;
1189	/*
1190	 * Process linemode suboptions.
1191	 */
1192	if (SB_EOF())
1193	    break;		/* garbage was sent */
1194	request = SB_GET();	/* get will/wont */
1195
1196	if (SB_EOF())
1197	    break;		/* another garbage check */
1198
1199	if (request == LM_SLC) {  /* SLC is not preceded by WILL or WONT */
1200		/*
1201		 * Process suboption buffer of slc's
1202		 */
1203		start_slc(1);
1204		do_opt_slc(subpointer, SB_LEN());
1205		(void) end_slc(0);
1206		break;
1207	} else if (request == LM_MODE) {
1208		if (SB_EOF())
1209		    return;
1210		useeditmode = SB_GET();  /* get mode flag */
1211		clientstat(LM_MODE, 0, 0);
1212		break;
1213	}
1214
1215	if (SB_EOF())
1216	    break;
1217	switch (SB_GET()) {  /* what suboption? */
1218	case LM_FORWARDMASK:
1219		/*
1220		 * According to spec, only server can send request for
1221		 * forwardmask, and client can only return a positive response.
1222		 * So don't worry about it.
1223		 */
1224
1225	default:
1226		break;
1227	}
1228	break;
1229    }  /* end of case TELOPT_LINEMODE */
1230#endif
1231    case TELOPT_STATUS: {
1232	int mode;
1233
1234	if (SB_EOF())
1235	    break;
1236	mode = SB_GET();
1237	switch (mode) {
1238	case TELQUAL_SEND:
1239	    if (my_state_is_will(TELOPT_STATUS))
1240		send_status();
1241	    break;
1242
1243	case TELQUAL_IS:
1244	    break;
1245
1246	default:
1247	    break;
1248	}
1249	break;
1250    }  /* end of case TELOPT_STATUS */
1251
1252    case TELOPT_XDISPLOC: {
1253	if (SB_EOF() || SB_GET() != TELQUAL_IS)
1254		return;
1255	settimer(xdisplocsubopt);
1256	subpointer[SB_LEN()] = '\0';
1257	(void)setenv("DISPLAY", (char *)subpointer, 1);
1258	break;
1259    }  /* end of case TELOPT_XDISPLOC */
1260
1261    case TELOPT_NEW_ENVIRON:
1262    case TELOPT_OLD_ENVIRON: {
1263	int c;
1264	char *cp, *varp, *valp;
1265
1266	if (SB_EOF())
1267		return;
1268	c = SB_GET();
1269	if (c == TELQUAL_IS) {
1270		if (subchar == TELOPT_OLD_ENVIRON)
1271			settimer(oenvironsubopt);
1272		else
1273			settimer(environsubopt);
1274	} else if (c != TELQUAL_INFO) {
1275		return;
1276	}
1277
1278	if (subchar == TELOPT_NEW_ENVIRON) {
1279	    while (!SB_EOF()) {
1280		c = SB_GET();
1281		if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
1282			break;
1283	    }
1284	} else
1285	{
1286#ifdef	ENV_HACK
1287	    /*
1288	     * We only want to do this if we haven't already decided
1289	     * whether or not the other side has its VALUE and VAR
1290	     * reversed.
1291	     */
1292	    if (env_ovar < 0) {
1293		int last = -1;		/* invalid value */
1294		int empty = 0;
1295		int got_var = 0, got_value = 0, got_uservar = 0;
1296
1297		/*
1298		 * The other side might have its VALUE and VAR values
1299		 * reversed.  To be interoperable, we need to determine
1300		 * which way it is.  If the first recognized character
1301		 * is a VAR or VALUE, then that will tell us what
1302		 * type of client it is.  If the first recognized
1303		 * character is a USERVAR, then we continue scanning
1304		 * the suboption looking for two consecutive
1305		 * VAR or VALUE fields.  We should not get two
1306		 * consecutive VALUE fields, so finding two
1307		 * consecutive VALUE or VAR fields will tell us
1308		 * what the client is.
1309		 */
1310		SB_SAVE();
1311		while (!SB_EOF()) {
1312			c = SB_GET();
1313			switch(c) {
1314			case OLD_ENV_VAR:
1315				if (last < 0 || last == OLD_ENV_VAR
1316				    || (empty && (last == OLD_ENV_VALUE)))
1317					goto env_ovar_ok;
1318				got_var++;
1319				last = OLD_ENV_VAR;
1320				break;
1321			case OLD_ENV_VALUE:
1322				if (last < 0 || last == OLD_ENV_VALUE
1323				    || (empty && (last == OLD_ENV_VAR)))
1324					goto env_ovar_wrong;
1325				got_value++;
1326				last = OLD_ENV_VALUE;
1327				break;
1328			case ENV_USERVAR:
1329				/* count strings of USERVAR as one */
1330				if (last != ENV_USERVAR)
1331					got_uservar++;
1332				if (empty) {
1333					if (last == OLD_ENV_VALUE)
1334						goto env_ovar_ok;
1335					if (last == OLD_ENV_VAR)
1336						goto env_ovar_wrong;
1337				}
1338				last = ENV_USERVAR;
1339				break;
1340			case ENV_ESC:
1341				if (!SB_EOF())
1342					c = SB_GET();
1343				/* FALL THROUGH */
1344			default:
1345				empty = 0;
1346				continue;
1347			}
1348			empty = 1;
1349		}
1350		if (empty) {
1351			if (last == OLD_ENV_VALUE)
1352				goto env_ovar_ok;
1353			if (last == OLD_ENV_VAR)
1354				goto env_ovar_wrong;
1355		}
1356		/*
1357		 * Ok, the first thing was a USERVAR, and there
1358		 * are not two consecutive VAR or VALUE commands,
1359		 * and none of the VAR or VALUE commands are empty.
1360		 * If the client has sent us a well-formed option,
1361		 * then the number of VALUEs received should always
1362		 * be less than or equal to the number of VARs and
1363		 * USERVARs received.
1364		 *
1365		 * If we got exactly as many VALUEs as VARs and
1366		 * USERVARs, the client has the same definitions.
1367		 *
1368		 * If we got exactly as many VARs as VALUEs and
1369		 * USERVARS, the client has reversed definitions.
1370		 */
1371		if (got_uservar + got_var == got_value) {
1372	    env_ovar_ok:
1373			env_ovar = OLD_ENV_VAR;
1374			env_ovalue = OLD_ENV_VALUE;
1375		} else if (got_uservar + got_value == got_var) {
1376	    env_ovar_wrong:
1377			env_ovar = OLD_ENV_VALUE;
1378			env_ovalue = OLD_ENV_VAR;
1379			DIAG(TD_OPTIONS, {output_data(
1380				"ENVIRON VALUE and VAR are reversed!\r\n");});
1381
1382		}
1383	    }
1384	    SB_RESTORE();
1385#endif
1386
1387	    while (!SB_EOF()) {
1388		c = SB_GET();
1389		if ((c == env_ovar) || (c == ENV_USERVAR))
1390			break;
1391	    }
1392	}
1393
1394	if (SB_EOF())
1395		return;
1396
1397	cp = varp = (char *)subpointer;
1398	valp = 0;
1399
1400	while (!SB_EOF()) {
1401		c = SB_GET();
1402		if (subchar == TELOPT_OLD_ENVIRON) {
1403			if (c == env_ovar)
1404				c = NEW_ENV_VAR;
1405			else if (c == env_ovalue)
1406				c = NEW_ENV_VALUE;
1407		}
1408		switch (c) {
1409
1410		case NEW_ENV_VALUE:
1411			*cp = '\0';
1412			cp = valp = (char *)subpointer;
1413			break;
1414
1415		case NEW_ENV_VAR:
1416		case ENV_USERVAR:
1417			*cp = '\0';
1418			if (envvarok(varp)) {
1419				if (valp)
1420					(void)setenv(varp, valp, 1);
1421				else
1422					unsetenv(varp);
1423			}
1424			cp = varp = (char *)subpointer;
1425			valp = 0;
1426			break;
1427
1428		case ENV_ESC:
1429			if (SB_EOF())
1430				break;
1431			c = SB_GET();
1432			/* FALL THROUGH */
1433		default:
1434			*cp++ = c;
1435			break;
1436		}
1437	}
1438	*cp = '\0';
1439	if (envvarok(varp)) {
1440		if (valp)
1441			(void)setenv(varp, valp, 1);
1442		else
1443			unsetenv(varp);
1444	}
1445	break;
1446    }  /* end of case TELOPT_NEW_ENVIRON */
1447#ifdef AUTHENTICATION
1448    case TELOPT_AUTHENTICATION:
1449	if (SB_EOF())
1450		break;
1451	switch(SB_GET()) {
1452	case TELQUAL_SEND:
1453	case TELQUAL_REPLY:
1454		/*
1455		 * These are sent by us and cannot be sent by
1456		 * the client.
1457		 */
1458		break;
1459	case TELQUAL_IS:
1460		auth_is(subpointer, SB_LEN());
1461		break;
1462	case TELQUAL_NAME:
1463		auth_name(subpointer, SB_LEN());
1464		break;
1465	}
1466	break;
1467#endif
1468#ifdef	ENCRYPTION
1469    case TELOPT_ENCRYPT:
1470	if (SB_EOF())
1471		break;
1472	switch(SB_GET()) {
1473	case ENCRYPT_SUPPORT:
1474		encrypt_support(subpointer, SB_LEN());
1475		break;
1476	case ENCRYPT_IS:
1477		encrypt_is(subpointer, SB_LEN());
1478		break;
1479	case ENCRYPT_REPLY:
1480		encrypt_reply(subpointer, SB_LEN());
1481		break;
1482	case ENCRYPT_START:
1483		encrypt_start(subpointer, SB_LEN());
1484		break;
1485	case ENCRYPT_END:
1486		encrypt_end();
1487		break;
1488	case ENCRYPT_REQSTART:
1489		encrypt_request_start(subpointer, SB_LEN());
1490		break;
1491	case ENCRYPT_REQEND:
1492		/*
1493		 * We can always send an REQEND so that we cannot
1494		 * get stuck encrypting.  We should only get this
1495		 * if we have been able to get in the correct mode
1496		 * anyhow.
1497		 */
1498		encrypt_request_end();
1499		break;
1500	case ENCRYPT_ENC_KEYID:
1501		encrypt_enc_keyid(subpointer, SB_LEN());
1502		break;
1503	case ENCRYPT_DEC_KEYID:
1504		encrypt_dec_keyid(subpointer, SB_LEN());
1505		break;
1506	default:
1507		break;
1508	}
1509	break;
1510#endif	/* ENCRYPTION */
1511
1512    default:
1513	break;
1514    }  /* end of switch */
1515
1516}  /* end of suboption */
1517
1518#ifdef LINEMODE
1519void
1520doclientstat(void)
1521{
1522	clientstat(TELOPT_LINEMODE, WILL, 0);
1523}
1524#endif /* LINEMODE */
1525
1526void
1527send_status(void)
1528{
1529#define	ADD(c) \
1530	do { \
1531		if (ep > ncp) \
1532			*ncp++ = c; \
1533		else \
1534			goto trunc; \
1535	} while (0)
1536#define	ADD_DATA(c) \
1537	do { \
1538		ADD(c); if (c == SE || c == IAC) ADD(c); \
1539	} while (0)
1540
1541	unsigned char statusbuf[256];
1542	unsigned char *ep;
1543	unsigned char *ncp;
1544	unsigned char i;
1545
1546	ncp = statusbuf;
1547	ep = statusbuf + sizeof(statusbuf);
1548
1549	netflush();	/* get rid of anything waiting to go out */
1550
1551	ADD(IAC);
1552	ADD(SB);
1553	ADD(TELOPT_STATUS);
1554	ADD(TELQUAL_IS);
1555
1556	/*
1557	 * We check the want_state rather than the current state,
1558	 * because if we received a DO/WILL for an option that we
1559	 * don't support, and the other side didn't send a DONT/WONT
1560	 * in response to our WONT/DONT, then the "state" will be
1561	 * WILL/DO, and the "want_state" will be WONT/DONT.  We
1562	 * need to go by the latter.
1563	 */
1564	for (i = 0; i < (unsigned char)NTELOPTS; i++) {
1565		if (my_want_state_is_will(i)) {
1566			ADD(WILL);
1567			ADD_DATA(i);
1568		}
1569		if (his_want_state_is_will(i)) {
1570			ADD(DO);
1571			ADD_DATA(i);
1572		}
1573	}
1574
1575	if (his_want_state_is_will(TELOPT_LFLOW)) {
1576		ADD(SB);
1577		ADD(TELOPT_LFLOW);
1578		if (flowmode) {
1579			ADD(LFLOW_ON);
1580		} else {
1581			ADD(LFLOW_OFF);
1582		}
1583		ADD(SE);
1584
1585		if (restartany >= 0) {
1586			ADD(SB);
1587			ADD(TELOPT_LFLOW);
1588			if (restartany) {
1589				ADD(LFLOW_RESTART_ANY);
1590			} else {
1591				ADD(LFLOW_RESTART_XON);
1592			}
1593			ADD(SE);
1594		}
1595	}
1596
1597#ifdef	LINEMODE
1598	if (his_want_state_is_will(TELOPT_LINEMODE)) {
1599		unsigned char *cp, *cpe;
1600		int len;
1601
1602		ADD(SB);
1603		ADD(TELOPT_LINEMODE);
1604		ADD(LM_MODE);
1605		ADD_DATA(editmode);
1606		ADD(SE);
1607
1608		ADD(SB);
1609		ADD(TELOPT_LINEMODE);
1610		ADD(LM_SLC);
1611		start_slc(0);
1612		send_slc();
1613		len = end_slc(&cp);
1614		for (cpe = cp + len; cp < cpe; cp++)
1615			ADD_DATA(*cp);
1616		ADD(SE);
1617	}
1618#endif	/* LINEMODE */
1619
1620	ADD(IAC);
1621	ADD(SE);
1622
1623	writenet(statusbuf, ncp - statusbuf);
1624	netflush();	/* Send it on its way */
1625
1626	DIAG(TD_OPTIONS,
1627		{printsub('>', statusbuf, ncp - statusbuf); netflush();});
1628	return;
1629
1630trunc:
1631	/* XXX bark? */
1632	return;
1633#undef ADD
1634#undef ADD_DATA
1635}
1636
1637int
1638output_data(const char *format, ...)
1639{
1640	va_list args;
1641	size_t remaining, ret;
1642
1643	va_start(args, format);
1644	remaining = BUFSIZ - (nfrontp - netobuf);
1645	/* try a netflush() if the room is too low */
1646	if (strlen(format) > remaining || BUFSIZ / 4 > remaining) {
1647		netflush();
1648		remaining = BUFSIZ - (nfrontp - netobuf);
1649	}
1650	ret = vsnprintf(nfrontp, remaining, format, args);
1651	nfrontp += ((ret < remaining - 1) ? ret : remaining - 1);
1652	va_end(args);
1653	return ret;
1654}
1655
1656int
1657output_datalen(const char *buf, size_t l)
1658{
1659	size_t remaining;
1660
1661	remaining = BUFSIZ - (nfrontp - netobuf);
1662	if (remaining < l) {
1663		netflush();
1664		remaining = BUFSIZ - (nfrontp - netobuf);
1665	}
1666	if (remaining < l)
1667		return -1;
1668	memmove(nfrontp, buf, l);
1669	nfrontp += l;
1670	return (int)l;
1671}
1672