xref: /openbsd/usr.bin/telnet/telnet.c (revision fd84ef7e)
1 /*	$OpenBSD: telnet.c,v 1.13 2001/11/19 19:02:16 mpech Exp $	*/
2 /*	$NetBSD: telnet.c,v 1.7 1996/02/28 21:04:15 thorpej Exp $	*/
3 
4 /*
5  * Copyright (c) 1988, 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #include "telnet_locl.h"
38 #include <curses.h>
39 #include <term.h>
40 
41 #define        strip(x) (eight ? (x) : ((x) & 0x7f))
42 
43 static unsigned char	subbuffer[SUBBUFSIZE],
44 			*subpointer, *subend;	 /* buffer for sub-options */
45 #define	SB_CLEAR()	subpointer = subbuffer;
46 #define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
47 #define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \
48 				*subpointer++ = (c); \
49 			}
50 
51 #define	SB_GET()	((*subpointer++)&0xff)
52 #define	SB_PEEK()	((*subpointer)&0xff)
53 #define	SB_EOF()	(subpointer >= subend)
54 #define	SB_LEN()	(subend - subpointer)
55 
56 char	options[256];		/* The combined options */
57 char	do_dont_resp[256];
58 char	will_wont_resp[256];
59 
60 int
61 	eight = 3,
62 	binary = 0,
63 	autologin = 0,	/* Autologin anyone? */
64 	skiprc = 0,
65 	connected,
66 	showoptions,
67 	In3270,		/* Are we in 3270 mode? */
68 	ISend,		/* trying to send network data in */
69 	debug = 0,
70 	crmod,
71 	netdata,	/* Print out network data flow */
72 	crlf,		/* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
73 #if	defined(TN3270)
74 	noasynchtty = 0,/* User specified "-noasynch" on command line */
75 	noasynchnet = 0,/* User specified "-noasynch" on command line */
76 	askedSGA = 0,	/* We have talked about suppress go ahead */
77 #endif	/* defined(TN3270) */
78 	telnetport,
79 	SYNCHing,	/* we are in TELNET SYNCH mode */
80 	flushout,	/* flush output */
81 	autoflush = 0,	/* flush output when interrupting? */
82 	autosynch,	/* send interrupt characters with SYNCH? */
83 	localflow,	/* we handle flow control locally */
84 	restartany,	/* if flow control enabled, restart on any character */
85 	localchars,	/* we recognize interrupt/quit */
86 	donelclchars,	/* the user has set "localchars" */
87 	donebinarytoggle,	/* the user has put us in binary */
88 	dontlecho,	/* do we suppress local echoing right now? */
89 	globalmode,
90 	clienteof = 0;
91 
92 char *prompt = 0;
93 
94 cc_t escape;
95 cc_t rlogin;
96 #ifdef	KLUDGELINEMODE
97 cc_t echoc;
98 #endif
99 
100 /*
101  * Telnet receiver states for fsm
102  */
103 #define	TS_DATA		0
104 #define	TS_IAC		1
105 #define	TS_WILL		2
106 #define	TS_WONT		3
107 #define	TS_DO		4
108 #define	TS_DONT		5
109 #define	TS_CR		6
110 #define	TS_SB		7		/* sub-option collection */
111 #define	TS_SE		8		/* looking for sub-option end */
112 
113 static int	telrcv_state;
114 #ifdef	OLD_ENVIRON
115 unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
116 #else
117 # define telopt_environ TELOPT_NEW_ENVIRON
118 #endif
119 
120 jmp_buf	toplevel = { 0 };
121 jmp_buf	peerdied;
122 
123 int	flushline;
124 int	linemode;
125 
126 #ifdef	KLUDGELINEMODE
127 int	kludgelinemode = 1;
128 #endif
129 
130 /*
131  * The following are some clocks used to decide how to interpret
132  * the relationship between various variables.
133  */
134 
135 Clocks clocks;
136 
137 
138 /*
139  * Initialize telnet environment.
140  */
141 
142     void
143 init_telnet()
144 {
145     env_init();
146 
147     SB_CLEAR();
148     memset((char *)options, 0, sizeof options);
149 
150     connected = In3270 = ISend = localflow = donebinarytoggle = 0;
151 #if	defined(AUTHENTICATION) || defined(ENCRYPTION)
152     auth_encrypt_connect(connected);
153 #endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
154     restartany = -1;
155 
156     SYNCHing = 0;
157 
158     /* Don't change NetTrace */
159 
160     escape = CONTROL(']');
161     rlogin = _POSIX_VDISABLE;
162 #ifdef	KLUDGELINEMODE
163     echoc = CONTROL('E');
164 #endif
165 
166     flushline = 1;
167     telrcv_state = TS_DATA;
168 }
169 
170 
171 /*
172  * These routines are in charge of sending option negotiations
173  * to the other side.
174  *
175  * The basic idea is that we send the negotiation if either side
176  * is in disagreement as to what the current state should be.
177  */
178 
179     void
180 send_do(c, init)
181     int c, init;
182 {
183     if (init) {
184 	if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
185 				my_want_state_is_do(c))
186 	    return;
187 	set_my_want_state_do(c);
188 	do_dont_resp[c]++;
189     }
190     NET2ADD(IAC, DO);
191     NETADD(c);
192     printoption("SENT",DO, c);
193 }
194 
195     void
196 send_dont(c, init)
197     int c, init;
198 {
199     if (init) {
200 	if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
201 				my_want_state_is_dont(c))
202 	    return;
203 	set_my_want_state_dont(c);
204 	do_dont_resp[c]++;
205     }
206     NET2ADD(IAC, DONT);
207     NETADD(c);
208     printoption("SENT", DONT, c);
209 }
210 
211     void
212 send_will(c, init)
213     int c, init;
214 {
215     if (init) {
216 	if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
217 				my_want_state_is_will(c))
218 	    return;
219 	set_my_want_state_will(c);
220 	will_wont_resp[c]++;
221     }
222     NET2ADD(IAC, WILL);
223     NETADD(c);
224     printoption("SENT", WILL, c);
225 }
226 
227     void
228 send_wont(c, init)
229     int c, init;
230 {
231     if (init) {
232 	if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
233 				my_want_state_is_wont(c))
234 	    return;
235 	set_my_want_state_wont(c);
236 	will_wont_resp[c]++;
237     }
238     NET2ADD(IAC, WONT);
239     NETADD(c);
240     printoption("SENT", WONT, c);
241 }
242 
243 
244 	void
245 willoption(option)
246 	int option;
247 {
248 	int new_state_ok = 0;
249 
250 	if (do_dont_resp[option]) {
251 	    --do_dont_resp[option];
252 	    if (do_dont_resp[option] && my_state_is_do(option))
253 		--do_dont_resp[option];
254 	}
255 
256 	if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
257 
258 	    switch (option) {
259 
260 	    case TELOPT_ECHO:
261 #	    if defined(TN3270)
262 		/*
263 		 * The following is a pain in the rear-end.
264 		 * Various IBM servers (some versions of Wiscnet,
265 		 * possibly Fibronics/Spartacus, and who knows who
266 		 * else) will NOT allow us to send "DO SGA" too early
267 		 * in the setup proceedings.  On the other hand,
268 		 * 4.2 servers (telnetd) won't set SGA correctly.
269 		 * So, we are stuck.  Empirically (but, based on
270 		 * a VERY small sample), the IBM servers don't send
271 		 * out anything about ECHO, so we postpone our sending
272 		 * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
273 		 * DO send).
274 		  */
275 		{
276 		    if (askedSGA == 0) {
277 			askedSGA = 1;
278 			if (my_want_state_is_dont(TELOPT_SGA))
279 			    send_do(TELOPT_SGA, 1);
280 		    }
281 		}
282 		    /* Fall through */
283 	    case TELOPT_EOR:
284 #endif	    /* defined(TN3270) */
285 	    case TELOPT_BINARY:
286 	    case TELOPT_SGA:
287 		settimer(modenegotiated);
288 		/* FALL THROUGH */
289 	    case TELOPT_STATUS:
290 #if	defined(AUTHENTICATION)
291 	    case TELOPT_AUTHENTICATION:
292 #endif
293 #if    defined(ENCRYPTION)
294 	    case TELOPT_ENCRYPT:
295 #endif
296 		new_state_ok = 1;
297 		break;
298 
299 	    case TELOPT_TM:
300 		if (flushout)
301 		    flushout = 0;
302 		/*
303 		 * Special case for TM.  If we get back a WILL,
304 		 * pretend we got back a WONT.
305 		 */
306 		set_my_want_state_dont(option);
307 		set_my_state_dont(option);
308 		return;			/* Never reply to TM will's/wont's */
309 
310 	    case TELOPT_LINEMODE:
311 	    default:
312 		break;
313 	    }
314 
315 	    if (new_state_ok) {
316 		set_my_want_state_do(option);
317 		send_do(option, 0);
318 		setconnmode(0);		/* possibly set new tty mode */
319 	    } else {
320 		do_dont_resp[option]++;
321 		send_dont(option, 0);
322 	    }
323 	}
324 	set_my_state_do(option);
325 #if    defined(ENCRYPTION)
326 	if (option == TELOPT_ENCRYPT)
327 		encrypt_send_support();
328 #endif
329 
330 }
331 
332 	void
333 wontoption(option)
334 	int option;
335 {
336 	if (do_dont_resp[option]) {
337 	    --do_dont_resp[option];
338 	    if (do_dont_resp[option] && my_state_is_dont(option))
339 		--do_dont_resp[option];
340 	}
341 
342 	if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
343 
344 	    switch (option) {
345 
346 #ifdef	KLUDGELINEMODE
347 	    case TELOPT_SGA:
348 		if (!kludgelinemode)
349 		    break;
350 		/* FALL THROUGH */
351 #endif
352 	    case TELOPT_ECHO:
353 		settimer(modenegotiated);
354 		break;
355 
356 	    case TELOPT_TM:
357 		if (flushout)
358 		    flushout = 0;
359 		set_my_want_state_dont(option);
360 		set_my_state_dont(option);
361 		return;		/* Never reply to TM will's/wont's */
362 
363 #ifdef ENCRYPTION
364 	    case TELOPT_ENCRYPT:
365 		encrypt_not();
366 		break;
367 #endif
368 	    default:
369 		break;
370 	    }
371 	    set_my_want_state_dont(option);
372 	    if (my_state_is_do(option))
373 		send_dont(option, 0);
374 	    setconnmode(0);			/* Set new tty mode */
375 	} else if (option == TELOPT_TM) {
376 	    /*
377 	     * Special case for TM.
378 	     */
379 	    if (flushout)
380 		flushout = 0;
381 	    set_my_want_state_dont(option);
382 	}
383 	set_my_state_dont(option);
384 }
385 
386 	static void
387 dooption(option)
388 	int option;
389 {
390 	int new_state_ok = 0;
391 
392 	if (will_wont_resp[option]) {
393 	    --will_wont_resp[option];
394 	    if (will_wont_resp[option] && my_state_is_will(option))
395 		--will_wont_resp[option];
396 	}
397 
398 	if (will_wont_resp[option] == 0) {
399 	  if (my_want_state_is_wont(option)) {
400 
401 	    switch (option) {
402 
403 	    case TELOPT_TM:
404 		/*
405 		 * Special case for TM.  We send a WILL, but pretend
406 		 * we sent WONT.
407 		 */
408 		send_will(option, 0);
409 		set_my_want_state_wont(TELOPT_TM);
410 		set_my_state_wont(TELOPT_TM);
411 		return;
412 
413 #	if defined(TN3270)
414 	    case TELOPT_EOR:		/* end of record */
415 #	endif	/* defined(TN3270) */
416 	    case TELOPT_BINARY:		/* binary mode */
417 	    case TELOPT_NAWS:		/* window size */
418 	    case TELOPT_TSPEED:		/* terminal speed */
419 	    case TELOPT_LFLOW:		/* local flow control */
420 	    case TELOPT_TTYPE:		/* terminal type option */
421 	    case TELOPT_SGA:		/* no big deal */
422 #if    defined(ENCRYPTION)
423 	    case TELOPT_ENCRYPT:        /* encryption variable option */
424 #endif
425 		new_state_ok = 1;
426 		break;
427 
428 	    case TELOPT_NEW_ENVIRON:	/* New environment variable option */
429 #ifdef	OLD_ENVIRON
430 		if (my_state_is_will(TELOPT_OLD_ENVIRON))
431 			send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
432 		goto env_common;
433 	    case TELOPT_OLD_ENVIRON:	/* Old environment variable option */
434 		if (my_state_is_will(TELOPT_NEW_ENVIRON))
435 			break;		/* Don't enable if new one is in use! */
436 	    env_common:
437 		telopt_environ = option;
438 #endif
439 		new_state_ok = 1;
440 		break;
441 
442 #if	defined(AUTHENTICATION)
443 	    case TELOPT_AUTHENTICATION:
444 		if (autologin)
445 			new_state_ok = 1;
446 		break;
447 #endif
448 
449 	    case TELOPT_XDISPLOC:	/* X Display location */
450 		if (env_getvalue((unsigned char *)"DISPLAY"))
451 		    new_state_ok = 1;
452 		break;
453 
454 	    case TELOPT_LINEMODE:
455 #ifdef	KLUDGELINEMODE
456 		kludgelinemode = 0;
457 		send_do(TELOPT_SGA, 1);
458 #endif
459 		set_my_want_state_will(TELOPT_LINEMODE);
460 		send_will(option, 0);
461 		set_my_state_will(TELOPT_LINEMODE);
462 		slc_init();
463 		return;
464 
465 	    case TELOPT_ECHO:		/* We're never going to echo... */
466 	    default:
467 		break;
468 	    }
469 
470 	    if (new_state_ok) {
471 		set_my_want_state_will(option);
472 		send_will(option, 0);
473 		setconnmode(0);			/* Set new tty mode */
474 	    } else {
475 		will_wont_resp[option]++;
476 		send_wont(option, 0);
477 	    }
478 	  } else {
479 	    /*
480 	     * Handle options that need more things done after the
481 	     * other side has acknowledged the option.
482 	     */
483 	    switch (option) {
484 	    case TELOPT_LINEMODE:
485 #ifdef	KLUDGELINEMODE
486 		kludgelinemode = 0;
487 		send_do(TELOPT_SGA, 1);
488 #endif
489 		set_my_state_will(option);
490 		slc_init();
491 		send_do(TELOPT_SGA, 0);
492 		return;
493 	    }
494 	  }
495 	}
496 	set_my_state_will(option);
497 }
498 
499 	static void
500 dontoption(option)
501 	int option;
502 {
503 
504 	if (will_wont_resp[option]) {
505 	    --will_wont_resp[option];
506 	    if (will_wont_resp[option] && my_state_is_wont(option))
507 		--will_wont_resp[option];
508 	}
509 
510 	if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
511 	    switch (option) {
512 	    case TELOPT_LINEMODE:
513 		linemode = 0;	/* put us back to the default state */
514 		break;
515 #ifdef	OLD_ENVIRON
516 	    case TELOPT_NEW_ENVIRON:
517 		/*
518 		 * The new environ option wasn't recognized, try
519 		 * the old one.
520 		 */
521 		send_will(TELOPT_OLD_ENVIRON, 1);
522 		telopt_environ = TELOPT_OLD_ENVIRON;
523 		break;
524 #endif
525 	    }
526 	    /* we always accept a DONT */
527 	    set_my_want_state_wont(option);
528 	    if (my_state_is_will(option))
529 		send_wont(option, 0);
530 	    setconnmode(0);			/* Set new tty mode */
531 	}
532 	set_my_state_wont(option);
533 }
534 
535 /*
536  * This routine will turn a pipe separated list of names in the buffer
537  * into an array of pointers to NUL terminated names.  We toss out any
538  * bad, duplicate, or verbose names (names with spaces).
539  */
540 
541 int is_unique P((char *, char **, char **));
542 
543 static char *name_unknown = "UNKNOWN";
544 static char *unknown[] = { 0, 0 };
545 
546 	char **
547 mklist(buf, name)
548 	char *buf, *name;
549 {
550 	int n;
551 	char c, *cp, **argvp, *cp2, **argv, **avt;
552 
553 	if (name) {
554 		if ((int)strlen(name) > 40) {
555 			name = 0;
556 			unknown[0] = name_unknown;
557 		} else {
558 			unknown[0] = name;
559 			upcase(name);
560 		}
561 	} else
562 		unknown[0] = name_unknown;
563 	/*
564 	 * Count up the number of names.
565 	 */
566 	for (n = 1, cp = buf; *cp; cp++) {
567 		if (*cp == '|')
568 			n++;
569 	}
570 	/*
571 	 * Allocate an array to put the name pointers into
572 	 */
573 	argv = (char **)malloc((n+3)*sizeof(char *));
574 	if (argv == 0)
575 		return(unknown);
576 
577 	/*
578 	 * Fill up the array of pointers to names.
579 	 */
580 	*argv = 0;
581 	argvp = argv+1;
582 	n = 0;
583 	for (cp = cp2 = buf; (c = *cp);  cp++) {
584 		if (c == '|' || c == ':') {
585 			*cp++ = '\0';
586 			/*
587 			 * Skip entries that have spaces or are over 40
588 			 * characters long.  If this is our environment
589 			 * name, then put it up front.  Otherwise, as
590 			 * long as this is not a duplicate name (case
591 			 * insensitive) add it to the list.
592 			 */
593 			if (n || (cp - cp2 > 41))
594 				;
595 			else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
596 				*argv = cp2;
597 			else if (is_unique(cp2, argv+1, argvp))
598 				*argvp++ = cp2;
599 			if (c == ':')
600 				break;
601 			/*
602 			 * Skip multiple delimiters. Reset cp2 to
603 			 * the beginning of the next name. Reset n,
604 			 * the flag for names with spaces.
605 			 */
606 			while ((c = *cp) == '|')
607 				cp++;
608 			cp2 = cp;
609 			n = 0;
610 		}
611 		/*
612 		 * Skip entries with spaces or non-ascii values.
613 		 * Convert lower case letters to upper case.
614 		 */
615 #define ISASCII(c) (!((c)&0x80))
616 		if ((c == ' ') || !ISASCII(c))
617 			n = 1;
618 		else if (islower(c))
619 			*cp = toupper(c);
620 	}
621 
622 	/*
623 	 * Check for an old V6 2 character name.  If the second
624 	 * name points to the beginning of the buffer, and is
625 	 * only 2 characters long, move it to the end of the array.
626 	 */
627 	if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
628 		--argvp;
629 		for (avt = &argv[1]; avt < argvp; avt++)
630 			*avt = *(avt+1);
631 		*argvp++ = buf;
632 	}
633 
634 	/*
635 	 * Duplicate last name, for TTYPE option, and null
636 	 * terminate the array.  If we didn't find a match on
637 	 * our terminal name, put that name at the beginning.
638 	 */
639 	cp = *(argvp-1);
640 	*argvp++ = cp;
641 	*argvp = 0;
642 
643 	if (*argv == 0) {
644 		if (name)
645 			*argv = name;
646 		else {
647 			--argvp;
648 			for (avt = argv; avt < argvp; avt++)
649 				*avt = *(avt+1);
650 		}
651 	}
652 	if (*argv)
653 		return(argv);
654 	else
655 		return(unknown);
656 }
657 
658 	int
659 is_unique(name, as, ae)
660 	char *name, **as, **ae;
661 {
662 	char **ap;
663 	int n;
664 
665 	n = strlen(name) + 1;
666 	for (ap = as; ap < ae; ap++)
667 		if (strncasecmp(*ap, name, n) == 0)
668 			return(0);
669 	return (1);
670 }
671 
672 int resettermname = 1;
673 
674 	char *
675 gettermname()
676 {
677 	char *tname;
678 	static char **tnamep = 0;
679 	static char **next;
680 	int errret;
681 
682 	if (resettermname) {
683 		resettermname = 0;
684 		if (tnamep && tnamep != unknown)
685 			free(tnamep);
686 		if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
687 				(setupterm(tname, 1, &errret) == OK)) {
688 			tnamep = mklist(ttytype, tname);
689 		} else {
690 			if (tname && ((int)strlen(tname) <= 40)) {
691 				unknown[0] = tname;
692 				upcase(tname);
693 			} else
694 				unknown[0] = name_unknown;
695 			tnamep = unknown;
696 		}
697 		next = tnamep;
698 	}
699 	if (*next == 0)
700 		next = tnamep;
701 	return(*next++);
702 }
703 /*
704  * suboption()
705  *
706  *	Look at the sub-option buffer, and try to be helpful to the other
707  * side.
708  *
709  *	Currently we recognize:
710  *
711  *		Terminal type, send request.
712  *		Terminal speed (send request).
713  *		Local flow control (is request).
714  *		Linemode
715  */
716 
717     static void
718 suboption()
719 {
720     unsigned char subchar;
721 
722     printsub('<', subbuffer, SB_LEN()+2);
723     switch (subchar = SB_GET()) {
724     case TELOPT_TTYPE:
725 	if (my_want_state_is_wont(TELOPT_TTYPE))
726 	    return;
727 	if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
728 	    return;
729 	} else {
730 	    char *name;
731 	    unsigned char temp[50];
732 	    int len;
733 
734 #if	defined(TN3270)
735 	    if (tn3270_ttype()) {
736 		return;
737 	    }
738 #endif	/* defined(TN3270) */
739 	    name = gettermname();
740 	    len = strlen(name) + 4 + 2;
741 	    if (len < NETROOM()) {
742 		snprintf((char *)temp, sizeof(temp),
743 			 "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
744 			 TELQUAL_IS, name, IAC, SE);
745 		ring_supply_data(&netoring, temp, len);
746 		printsub('>', &temp[2], len-2);
747 	    } else {
748 		ExitString("No room in buffer for terminal type.\n", 1);
749 		/*NOTREACHED*/
750 	    }
751 	}
752 	break;
753     case TELOPT_TSPEED:
754 	if (my_want_state_is_wont(TELOPT_TSPEED))
755 	    return;
756 	if (SB_EOF())
757 	    return;
758 	if (SB_GET() == TELQUAL_SEND) {
759 	    long ospeed, ispeed;
760 	    unsigned char temp[50];
761 	    int len;
762 
763 	    TerminalSpeeds(&ispeed, &ospeed);
764 
765 	    snprintf((char *)temp, sizeof(temp),
766 		     "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
767 		     TELQUAL_IS, ospeed, ispeed, IAC, SE);
768 	    len = strlen((char *)temp+4) + 4;	/* temp[3] is 0 ... */
769 
770 	    if (len < NETROOM()) {
771 		ring_supply_data(&netoring, temp, len);
772 		printsub('>', temp+2, len - 2);
773 	    }
774 /*@*/	    else printf("lm_will: not enough room in buffer\n");
775 	}
776 	break;
777     case TELOPT_LFLOW:
778 	if (my_want_state_is_wont(TELOPT_LFLOW))
779 	    return;
780 	if (SB_EOF())
781 	    return;
782 	switch(SB_GET()) {
783 	case LFLOW_RESTART_ANY:
784 	    restartany = 1;
785 	    break;
786 	case LFLOW_RESTART_XON:
787 	    restartany = 0;
788 	    break;
789 	case LFLOW_ON:
790 	    localflow = 1;
791 	    break;
792 	case LFLOW_OFF:
793 	    localflow = 0;
794 	    break;
795 	default:
796 	    return;
797 	}
798 	setcommandmode();
799 	setconnmode(0);
800 	break;
801 
802     case TELOPT_LINEMODE:
803 	if (my_want_state_is_wont(TELOPT_LINEMODE))
804 	    return;
805 	if (SB_EOF())
806 	    return;
807 	switch (SB_GET()) {
808 	case WILL:
809 	    lm_will(subpointer, SB_LEN());
810 	    break;
811 	case WONT:
812 	    lm_wont(subpointer, SB_LEN());
813 	    break;
814 	case DO:
815 	    lm_do(subpointer, SB_LEN());
816 	    break;
817 	case DONT:
818 	    lm_dont(subpointer, SB_LEN());
819 	    break;
820 	case LM_SLC:
821 	    slc(subpointer, SB_LEN());
822 	    break;
823 	case LM_MODE:
824 	    lm_mode(subpointer, SB_LEN(), 0);
825 	    break;
826 	default:
827 	    break;
828 	}
829 	break;
830 
831 #ifdef	OLD_ENVIRON
832     case TELOPT_OLD_ENVIRON:
833 #endif
834     case TELOPT_NEW_ENVIRON:
835 	if (SB_EOF())
836 	    return;
837 	switch(SB_PEEK()) {
838 	case TELQUAL_IS:
839 	case TELQUAL_INFO:
840 	    if (my_want_state_is_dont(subchar))
841 		return;
842 	    break;
843 	case TELQUAL_SEND:
844 	    if (my_want_state_is_wont(subchar)) {
845 		return;
846 	    }
847 	    break;
848 	default:
849 	    return;
850 	}
851 	env_opt(subpointer, SB_LEN());
852 	break;
853 
854     case TELOPT_XDISPLOC:
855 	if (my_want_state_is_wont(TELOPT_XDISPLOC))
856 	    return;
857 	if (SB_EOF())
858 	    return;
859 	if (SB_GET() == TELQUAL_SEND) {
860 	    unsigned char temp[50], *dp;
861 	    int len;
862 
863 	    if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
864 		/*
865 		 * Something happened, we no longer have a DISPLAY
866 		 * variable.  So, turn off the option.
867 		 */
868 		send_wont(TELOPT_XDISPLOC, 1);
869 		break;
870 	    }
871 	    snprintf((char *)temp, sizeof(temp),
872 		    "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
873 		    TELQUAL_IS, dp, IAC, SE);
874 	    len = strlen((char *)temp+4) + 4;	/* temp[3] is 0 ... */
875 
876 	    if (len < NETROOM()) {
877 		ring_supply_data(&netoring, temp, len);
878 		printsub('>', temp+2, len - 2);
879 	    }
880 /*@*/	    else printf("lm_will: not enough room in buffer\n");
881 	}
882 	break;
883 
884 #if	defined(AUTHENTICATION)
885 	case TELOPT_AUTHENTICATION: {
886 		if (!autologin)
887 			break;
888 		if (SB_EOF())
889 			return;
890 		switch(SB_GET()) {
891 		case TELQUAL_IS:
892 			if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
893 				return;
894 			auth_is(subpointer, SB_LEN());
895 			break;
896 		case TELQUAL_SEND:
897 			if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
898 				return;
899 			auth_send(subpointer, SB_LEN());
900 			break;
901 		case TELQUAL_REPLY:
902 			if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
903 				return;
904 			auth_reply(subpointer, SB_LEN());
905 			break;
906 		case TELQUAL_NAME:
907 			if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
908 				return;
909 			auth_name(subpointer, SB_LEN());
910 			break;
911 		}
912 	}
913 	break;
914 #endif
915 #if    defined(ENCRYPTION)
916 	case TELOPT_ENCRYPT:
917 		if (SB_EOF())
918 			return;
919 		switch(SB_GET()) {
920 		case ENCRYPT_START:
921 			if (my_want_state_is_dont(TELOPT_ENCRYPT))
922 				return;
923 			encrypt_start(subpointer, SB_LEN());
924 			break;
925                case ENCRYPT_END:
926 			if (my_want_state_is_dont(TELOPT_ENCRYPT))
927 				return;
928 			encrypt_end();
929 			break;
930                case ENCRYPT_SUPPORT:
931                         if (my_want_state_is_wont(TELOPT_ENCRYPT))
932                                 return;
933 			encrypt_support(subpointer, SB_LEN());
934 			break;
935                case ENCRYPT_REQSTART:
936                         if (my_want_state_is_wont(TELOPT_ENCRYPT))
937 			        return;
938 			encrypt_request_start(subpointer, SB_LEN());
939 			break;
940                case ENCRYPT_REQEND:
941                         if (my_want_state_is_wont(TELOPT_ENCRYPT))
942                                 return;
943 			/*
944 			 * We can always send an REQEND so that we cannot
945 			 * get stuck encrypting.  We should only get this
946 			 * if we have been able to get in the correct mode
947 			 * anyhow.
948 			 */
949 			encrypt_request_end();
950 			break;
951                case ENCRYPT_IS:
952                         if (my_want_state_is_dont(TELOPT_ENCRYPT))
953                                 return;
954 			encrypt_is(subpointer, SB_LEN());
955 			break;
956                case ENCRYPT_REPLY:
957 		        if (my_want_state_is_wont(TELOPT_ENCRYPT))
958                                 return;
959 			encrypt_reply(subpointer, SB_LEN());
960 			break;
961                case ENCRYPT_ENC_KEYID:
962                         if (my_want_state_is_dont(TELOPT_ENCRYPT))
963                                 return;
964                         encrypt_enc_keyid(subpointer, SB_LEN());
965                         break;
966                case ENCRYPT_DEC_KEYID:
967                         if (my_want_state_is_wont(TELOPT_ENCRYPT))
968                                 return;
969                         encrypt_dec_keyid(subpointer, SB_LEN());
970                         break;
971                default:
972                         break;
973                }
974                break;
975 #endif
976     default:
977 	break;
978     }
979 }
980 
981 static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
982 
983     void
984 lm_will(cmd, len)
985     unsigned char *cmd;
986     int len;
987 {
988     if (len < 1) {
989 /*@*/	printf("lm_will: no command!!!\n");	/* Should not happen... */
990 	return;
991     }
992     switch(cmd[0]) {
993     case LM_FORWARDMASK:	/* We shouldn't ever get this... */
994     default:
995 	str_lm[3] = DONT;
996 	str_lm[4] = cmd[0];
997 	if (NETROOM() > sizeof(str_lm)) {
998 	    ring_supply_data(&netoring, str_lm, sizeof(str_lm));
999 	    printsub('>', &str_lm[2], sizeof(str_lm)-2);
1000 	}
1001 /*@*/	else printf("lm_will: not enough room in buffer\n");
1002 	break;
1003     }
1004 }
1005 
1006     void
1007 lm_wont(cmd, len)
1008     unsigned char *cmd;
1009     int len;
1010 {
1011     if (len < 1) {
1012 /*@*/	printf("lm_wont: no command!!!\n");	/* Should not happen... */
1013 	return;
1014     }
1015     switch(cmd[0]) {
1016     case LM_FORWARDMASK:	/* We shouldn't ever get this... */
1017     default:
1018 	/* We are always DONT, so don't respond */
1019 	return;
1020     }
1021 }
1022 
1023     void
1024 lm_do(cmd, len)
1025     unsigned char *cmd;
1026     int len;
1027 {
1028     if (len < 1) {
1029 /*@*/	printf("lm_do: no command!!!\n");	/* Should not happen... */
1030 	return;
1031     }
1032     switch(cmd[0]) {
1033     case LM_FORWARDMASK:
1034     default:
1035 	str_lm[3] = WONT;
1036 	str_lm[4] = cmd[0];
1037 	if (NETROOM() > sizeof(str_lm)) {
1038 	    ring_supply_data(&netoring, str_lm, sizeof(str_lm));
1039 	    printsub('>', &str_lm[2], sizeof(str_lm)-2);
1040 	}
1041 /*@*/	else printf("lm_do: not enough room in buffer\n");
1042 	break;
1043     }
1044 }
1045 
1046     void
1047 lm_dont(cmd, len)
1048     unsigned char *cmd;
1049     int len;
1050 {
1051     if (len < 1) {
1052 /*@*/	printf("lm_dont: no command!!!\n");	/* Should not happen... */
1053 	return;
1054     }
1055     switch(cmd[0]) {
1056     case LM_FORWARDMASK:
1057     default:
1058 	/* we are always WONT, so don't respond */
1059 	break;
1060     }
1061 }
1062 
1063 static unsigned char str_lm_mode[] = {
1064 	IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
1065 };
1066 
1067 	void
1068 lm_mode(cmd, len, init)
1069 	unsigned char *cmd;
1070 	int len, init;
1071 {
1072 	if (len != 1)
1073 		return;
1074 	if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
1075 		return;
1076 	if (*cmd&MODE_ACK)
1077 		return;
1078 	linemode = *cmd&(MODE_MASK&~MODE_ACK);
1079 	str_lm_mode[4] = linemode;
1080 	if (!init)
1081 	    str_lm_mode[4] |= MODE_ACK;
1082 	if (NETROOM() > sizeof(str_lm_mode)) {
1083 	    ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
1084 	    printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
1085 	}
1086 /*@*/	else printf("lm_mode: not enough room in buffer\n");
1087 	setconnmode(0);	/* set changed mode */
1088 }
1089 
1090 
1091 
1092 /*
1093  * slc()
1094  * Handle special character suboption of LINEMODE.
1095  */
1096 
1097 struct spc {
1098 	cc_t val;
1099 	cc_t *valp;
1100 	char flags;	/* Current flags & level */
1101 	char mylevel;	/* Maximum level & flags */
1102 } spc_data[NSLC+1];
1103 
1104 #define SLC_IMPORT	0
1105 #define	SLC_EXPORT	1
1106 #define SLC_RVALUE	2
1107 static int slc_mode = SLC_EXPORT;
1108 
1109 	void
1110 slc_init()
1111 {
1112 	struct spc *spcp;
1113 
1114 	localchars = 1;
1115 	for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
1116 		spcp->val = 0;
1117 		spcp->valp = 0;
1118 		spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
1119 	}
1120 
1121 #define	initfunc(func, flags) { \
1122 					spcp = &spc_data[func]; \
1123 					if ((spcp->valp = tcval(func))) { \
1124 					    spcp->val = *spcp->valp; \
1125 					    spcp->mylevel = SLC_VARIABLE|flags; \
1126 					} else { \
1127 					    spcp->val = 0; \
1128 					    spcp->mylevel = SLC_DEFAULT; \
1129 					} \
1130 				    }
1131 
1132 	initfunc(SLC_SYNCH, 0);
1133 	/* No BRK */
1134 	initfunc(SLC_AO, 0);
1135 	initfunc(SLC_AYT, 0);
1136 	/* No EOR */
1137 	initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
1138 	initfunc(SLC_EOF, 0);
1139 #ifndef	SYSV_TERMIO
1140 	initfunc(SLC_SUSP, SLC_FLUSHIN);
1141 #endif
1142 	initfunc(SLC_EC, 0);
1143 	initfunc(SLC_EL, 0);
1144 #ifndef	SYSV_TERMIO
1145 	initfunc(SLC_EW, 0);
1146 	initfunc(SLC_RP, 0);
1147 	initfunc(SLC_LNEXT, 0);
1148 #endif
1149 	initfunc(SLC_XON, 0);
1150 	initfunc(SLC_XOFF, 0);
1151 #ifdef	SYSV_TERMIO
1152 	spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
1153 	spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
1154 #endif
1155 	initfunc(SLC_FORW1, 0);
1156 #ifdef	USE_TERMIO
1157 	initfunc(SLC_FORW2, 0);
1158 	/* No FORW2 */
1159 #endif
1160 
1161 	initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
1162 #undef	initfunc
1163 
1164 	if (slc_mode == SLC_EXPORT)
1165 		slc_export();
1166 	else
1167 		slc_import(1);
1168 
1169 }
1170 
1171     void
1172 slcstate()
1173 {
1174     printf("Special characters are %s values\n",
1175 		slc_mode == SLC_IMPORT ? "remote default" :
1176 		slc_mode == SLC_EXPORT ? "local" :
1177 					 "remote");
1178 }
1179 
1180     void
1181 slc_mode_export()
1182 {
1183     slc_mode = SLC_EXPORT;
1184     if (my_state_is_will(TELOPT_LINEMODE))
1185 	slc_export();
1186 }
1187 
1188     void
1189 slc_mode_import(def)
1190     int def;
1191 {
1192     slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
1193     if (my_state_is_will(TELOPT_LINEMODE))
1194 	slc_import(def);
1195 }
1196 
1197 unsigned char slc_import_val[] = {
1198 	IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
1199 };
1200 unsigned char slc_import_def[] = {
1201 	IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
1202 };
1203 
1204     void
1205 slc_import(def)
1206     int def;
1207 {
1208     if (NETROOM() > sizeof(slc_import_val)) {
1209 	if (def) {
1210 	    ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
1211 	    printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
1212 	} else {
1213 	    ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
1214 	    printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
1215 	}
1216     }
1217 /*@*/ else printf("slc_import: not enough room\n");
1218 }
1219 
1220     void
1221 slc_export()
1222 {
1223     struct spc *spcp;
1224 
1225     TerminalDefaultChars();
1226 
1227     slc_start_reply();
1228     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1229 	if (spcp->mylevel != SLC_NOSUPPORT) {
1230 	    if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1231 		spcp->flags = SLC_NOSUPPORT;
1232 	    else
1233 		spcp->flags = spcp->mylevel;
1234 	    if (spcp->valp)
1235 		spcp->val = *spcp->valp;
1236 	    slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1237 	}
1238     }
1239     slc_end_reply();
1240     (void)slc_update();
1241     setconnmode(1);	/* Make sure the character values are set */
1242 }
1243 
1244 	void
1245 slc(cp, len)
1246 	unsigned char *cp;
1247 	int len;
1248 {
1249 	struct spc *spcp;
1250 	int func,level;
1251 
1252 	slc_start_reply();
1253 
1254 	for (; len >= 3; len -=3, cp +=3) {
1255 
1256 		func = cp[SLC_FUNC];
1257 
1258 		if (func == 0) {
1259 			/*
1260 			 * Client side: always ignore 0 function.
1261 			 */
1262 			continue;
1263 		}
1264 		if (func > NSLC) {
1265 			if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
1266 				slc_add_reply(func, SLC_NOSUPPORT, 0);
1267 			continue;
1268 		}
1269 
1270 		spcp = &spc_data[func];
1271 
1272 		level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
1273 
1274 		if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
1275 		    ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
1276 			continue;
1277 		}
1278 
1279 		if (level == (SLC_DEFAULT|SLC_ACK)) {
1280 			/*
1281 			 * This is an error condition, the SLC_ACK
1282 			 * bit should never be set for the SLC_DEFAULT
1283 			 * level.  Our best guess to recover is to
1284 			 * ignore the SLC_ACK bit.
1285 			 */
1286 			cp[SLC_FLAGS] &= ~SLC_ACK;
1287 		}
1288 
1289 		if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
1290 			spcp->val = (cc_t)cp[SLC_VALUE];
1291 			spcp->flags = cp[SLC_FLAGS];	/* include SLC_ACK */
1292 			continue;
1293 		}
1294 
1295 		level &= ~SLC_ACK;
1296 
1297 		if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
1298 			spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
1299 			spcp->val = (cc_t)cp[SLC_VALUE];
1300 		}
1301 		if (level == SLC_DEFAULT) {
1302 			if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
1303 				spcp->flags = spcp->mylevel;
1304 			else
1305 				spcp->flags = SLC_NOSUPPORT;
1306 		}
1307 		slc_add_reply(func, spcp->flags, spcp->val);
1308 	}
1309 	slc_end_reply();
1310 	if (slc_update())
1311 		setconnmode(1);	/* set the  new character values */
1312 }
1313 
1314     void
1315 slc_check()
1316 {
1317     struct spc *spcp;
1318 
1319     slc_start_reply();
1320     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1321 	if (spcp->valp && spcp->val != *spcp->valp) {
1322 	    spcp->val = *spcp->valp;
1323 	    if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1324 		spcp->flags = SLC_NOSUPPORT;
1325 	    else
1326 		spcp->flags = spcp->mylevel;
1327 	    slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1328 	}
1329     }
1330     slc_end_reply();
1331     setconnmode(1);
1332 }
1333 
1334 
1335 unsigned char slc_reply[128];
1336 unsigned char *slc_replyp;
1337 
1338 	void
1339 slc_start_reply()
1340 {
1341 	slc_replyp = slc_reply;
1342 	*slc_replyp++ = IAC;
1343 	*slc_replyp++ = SB;
1344 	*slc_replyp++ = TELOPT_LINEMODE;
1345 	*slc_replyp++ = LM_SLC;
1346 }
1347 
1348 	void
1349 slc_add_reply(func, flags, value)
1350 	unsigned char func;
1351 	unsigned char flags;
1352 	cc_t value;
1353 {
1354 	if ((*slc_replyp++ = func) == IAC)
1355 		*slc_replyp++ = IAC;
1356 	if ((*slc_replyp++ = flags) == IAC)
1357 		*slc_replyp++ = IAC;
1358 	if ((*slc_replyp++ = (unsigned char)value) == IAC)
1359 		*slc_replyp++ = IAC;
1360 }
1361 
1362     void
1363 slc_end_reply()
1364 {
1365     int len;
1366 
1367     *slc_replyp++ = IAC;
1368     *slc_replyp++ = SE;
1369     len = slc_replyp - slc_reply;
1370     if (len <= 6)
1371 	return;
1372     if (NETROOM() > len) {
1373 	ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1374 	printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1375     }
1376 /*@*/else printf("slc_end_reply: not enough room\n");
1377 }
1378 
1379 	int
1380 slc_update()
1381 {
1382 	struct spc *spcp;
1383 	int need_update = 0;
1384 
1385 	for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1386 		if (!(spcp->flags&SLC_ACK))
1387 			continue;
1388 		spcp->flags &= ~SLC_ACK;
1389 		if (spcp->valp && (*spcp->valp != spcp->val)) {
1390 			*spcp->valp = spcp->val;
1391 			need_update = 1;
1392 		}
1393 	}
1394 	return(need_update);
1395 }
1396 
1397 #ifdef	OLD_ENVIRON
1398 # ifdef	ENV_HACK
1399 /*
1400  * Earlier version of telnet/telnetd from the BSD code had
1401  * the definitions of VALUE and VAR reversed.  To ensure
1402  * maximum interoperability, we assume that the server is
1403  * an older BSD server, until proven otherwise.  The newer
1404  * BSD servers should be able to handle either definition,
1405  * so it is better to use the wrong values if we don't
1406  * know what type of server it is.
1407  */
1408 int env_auto = 1;
1409 int old_env_var = OLD_ENV_VAR;
1410 int old_env_value = OLD_ENV_VALUE;
1411 # else
1412 #  define old_env_var OLD_ENV_VAR
1413 #  define old_env_value OLD_ENV_VALUE
1414 # endif
1415 #endif
1416 
1417 	void
1418 env_opt(buf, len)
1419 	unsigned char *buf;
1420 	int len;
1421 {
1422 	unsigned char *ep = 0, *epc = 0;
1423 	int i;
1424 
1425 	switch(buf[0]&0xff) {
1426 	case TELQUAL_SEND:
1427 		env_opt_start();
1428 		if (len == 1) {
1429 			env_opt_add(NULL);
1430 		} else for (i = 1; i < len; i++) {
1431 			switch (buf[i]&0xff) {
1432 #ifdef	OLD_ENVIRON
1433 			case OLD_ENV_VAR:
1434 # ifdef	ENV_HACK
1435 				if (telopt_environ == TELOPT_OLD_ENVIRON
1436 				    && env_auto) {
1437 					/* Server has the same definitions */
1438 					old_env_var = OLD_ENV_VAR;
1439 					old_env_value = OLD_ENV_VALUE;
1440 				}
1441 				/* FALL THROUGH */
1442 # endif
1443 			case OLD_ENV_VALUE:
1444 				/*
1445 				 * Although OLD_ENV_VALUE is not legal, we will
1446 				 * still recognize it, just in case it is an
1447 				 * old server that has VAR & VALUE mixed up...
1448 				 */
1449 				/* FALL THROUGH */
1450 #else
1451 			case NEW_ENV_VAR:
1452 #endif
1453 			case ENV_USERVAR:
1454 				if (ep) {
1455 					*epc = 0;
1456 					env_opt_add(ep);
1457 				}
1458 				ep = epc = &buf[i+1];
1459 				break;
1460 			case ENV_ESC:
1461 				i++;
1462 				/*FALL THROUGH*/
1463 			default:
1464 				if (epc)
1465 					*epc++ = buf[i];
1466 				break;
1467 			}
1468 		}
1469 		if (ep) {
1470 			*epc = 0;
1471 			env_opt_add(ep);
1472 		}
1473 		env_opt_end(1);
1474 		break;
1475 
1476 	case TELQUAL_IS:
1477 	case TELQUAL_INFO:
1478 		/* Ignore for now.  We shouldn't get it anyway. */
1479 		break;
1480 
1481 	default:
1482 		break;
1483 	}
1484 }
1485 
1486 #define	OPT_REPLY_SIZE	256
1487 unsigned char *opt_reply;
1488 unsigned char *opt_replyp;
1489 unsigned char *opt_replyend;
1490 
1491 	void
1492 env_opt_start()
1493 {
1494 	unsigned char *p;
1495 
1496 	if (opt_reply) {
1497 		p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
1498 		if (p == NULL)
1499 			free(opt_reply);
1500 	} else
1501 		p = (unsigned char *)malloc(OPT_REPLY_SIZE);
1502 	opt_reply = p;
1503 	if (opt_reply == NULL) {
1504 /*@*/		printf("env_opt_start: malloc()/realloc() failed!!!\n");
1505 		opt_reply = opt_replyp = opt_replyend = NULL;
1506 		return;
1507 	}
1508 	opt_replyp = opt_reply;
1509 	opt_replyend = opt_reply + OPT_REPLY_SIZE;
1510 	*opt_replyp++ = IAC;
1511 	*opt_replyp++ = SB;
1512 	*opt_replyp++ = telopt_environ;
1513 	*opt_replyp++ = TELQUAL_IS;
1514 }
1515 
1516 	void
1517 env_opt_start_info()
1518 {
1519 	env_opt_start();
1520 	if (opt_replyp)
1521 	    opt_replyp[-1] = TELQUAL_INFO;
1522 }
1523 
1524 	void
1525 env_opt_add(ep)
1526 	unsigned char *ep;
1527 {
1528 	unsigned char *vp, c;
1529 
1530 	if (opt_reply == NULL)		/*XXX*/
1531 		return;			/*XXX*/
1532 
1533 	if (ep == NULL || *ep == '\0') {
1534 		/* Send user defined variables first. */
1535 		env_default(1, 0);
1536 		while ((ep = env_default(0, 0)))
1537 			env_opt_add(ep);
1538 
1539 		/* Now add the list of well know variables.  */
1540 		env_default(1, 1);
1541 		while ((ep = env_default(0, 1)))
1542 			env_opt_add(ep);
1543 		return;
1544 	}
1545 	vp = env_getvalue(ep);
1546 	if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
1547 				strlen((char *)ep) + 6 > opt_replyend)
1548 	{
1549 		int len;
1550 		unsigned char *p;
1551 		opt_replyend += OPT_REPLY_SIZE;
1552 		len = opt_replyend - opt_reply;
1553 		p = (unsigned char *)realloc(opt_reply, len);
1554 		if (p == NULL)
1555 			free(opt_reply);
1556 		opt_reply = p;
1557 		if (opt_reply == NULL) {
1558 /*@*/			printf("env_opt_add: realloc() failed!!!\n");
1559 			opt_reply = opt_replyp = opt_replyend = NULL;
1560 			return;
1561 		}
1562 		opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
1563 		opt_replyend = opt_reply + len;
1564 	}
1565 	if (opt_welldefined((char *)ep))
1566 #ifdef	OLD_ENVIRON
1567 		if (telopt_environ == TELOPT_OLD_ENVIRON)
1568 			*opt_replyp++ = old_env_var;
1569 		else
1570 #endif
1571 			*opt_replyp++ = NEW_ENV_VAR;
1572 	else
1573 		*opt_replyp++ = ENV_USERVAR;
1574 	for (;;) {
1575 		while ((c = *ep++)) {
1576 			switch(c&0xff) {
1577 			case IAC:
1578 				*opt_replyp++ = IAC;
1579 				break;
1580 			case NEW_ENV_VAR:
1581 			case NEW_ENV_VALUE:
1582 			case ENV_ESC:
1583 			case ENV_USERVAR:
1584 				*opt_replyp++ = ENV_ESC;
1585 				break;
1586 			}
1587 			*opt_replyp++ = c;
1588 		}
1589 		if ((ep = vp)) {
1590 #ifdef	OLD_ENVIRON
1591 			if (telopt_environ == TELOPT_OLD_ENVIRON)
1592 				*opt_replyp++ = old_env_value;
1593 			else
1594 #endif
1595 				*opt_replyp++ = NEW_ENV_VALUE;
1596 			vp = NULL;
1597 		} else
1598 			break;
1599 	}
1600 }
1601 
1602 	int
1603 opt_welldefined(ep)
1604 	char *ep;
1605 {
1606 	if ((strcmp(ep, "USER") == 0) ||
1607 	    (strcmp(ep, "DISPLAY") == 0) ||
1608 	    (strcmp(ep, "PRINTER") == 0) ||
1609 	    (strcmp(ep, "SYSTEMTYPE") == 0) ||
1610 	    (strcmp(ep, "JOB") == 0) ||
1611 	    (strcmp(ep, "ACCT") == 0))
1612 		return(1);
1613 	return(0);
1614 }
1615 	void
1616 env_opt_end(emptyok)
1617 	int emptyok;
1618 {
1619 	int len;
1620 
1621 	len = opt_replyp - opt_reply + 2;
1622 	if (emptyok || len > 6) {
1623 		*opt_replyp++ = IAC;
1624 		*opt_replyp++ = SE;
1625 		if (NETROOM() > len) {
1626 			ring_supply_data(&netoring, opt_reply, len);
1627 			printsub('>', &opt_reply[2], len - 2);
1628 		}
1629 /*@*/		else printf("slc_end_reply: not enough room\n");
1630 	}
1631 	if (opt_reply) {
1632 		free(opt_reply);
1633 		opt_reply = opt_replyp = opt_replyend = NULL;
1634 	}
1635 }
1636 
1637 
1638 
1639     int
1640 telrcv()
1641 {
1642     int c;
1643     int scc;
1644     unsigned char *sbp;
1645     int count;
1646     int returnValue = 0;
1647 
1648     scc = 0;
1649     count = 0;
1650     while (TTYROOM() > 2) {
1651 	if (scc == 0) {
1652 	    if (count) {
1653 		ring_consumed(&netiring, count);
1654 		returnValue = 1;
1655 		count = 0;
1656 	    }
1657 	    sbp = netiring.consume;
1658 	    scc = ring_full_consecutive(&netiring);
1659 	    if (scc == 0) {
1660 		/* No more data coming in */
1661 		break;
1662 	    }
1663 	}
1664 
1665 	c = *sbp++ & 0xff, scc--; count++;
1666 #if    defined(ENCRYPTION)
1667 	if (decrypt_input)
1668                 c = (*decrypt_input)(c);
1669 #endif
1670 
1671 	switch (telrcv_state) {
1672 
1673 	case TS_CR:
1674 	    telrcv_state = TS_DATA;
1675 	    if (c == '\0') {
1676 		break;	/* Ignore \0 after CR */
1677 	    }
1678 	    else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1679 		TTYADD(c);
1680 		break;
1681 	    }
1682 	    /* Else, fall through */
1683 
1684 	case TS_DATA:
1685 	    if (c == IAC) {
1686 		telrcv_state = TS_IAC;
1687 		break;
1688 	    }
1689 #	    if defined(TN3270)
1690 	    if (In3270) {
1691 		*Ifrontp++ = c;
1692 		while (scc > 0) {
1693 		    c = *sbp++ & 0377, scc--; count++;
1694 		    if (c == IAC) {
1695 			telrcv_state = TS_IAC;
1696 			break;
1697 		    }
1698 		    *Ifrontp++ = c;
1699 		}
1700 	    } else
1701 #	    endif /* defined(TN3270) */
1702 		    /*
1703 		     * The 'crmod' hack (see following) is needed
1704 		     * since we can't set CRMOD on output only.
1705 		     * Machines like MULTICS like to send \r without
1706 		     * \n; since we must turn off CRMOD to get proper
1707 		     * input, the mapping is done here (sigh).
1708 		     */
1709 	    if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
1710 		if (scc > 0) {
1711 		    c = *sbp&0xff;
1712 #if    defined(ENCRYPTION)
1713 		    if (decrypt_input)
1714                         c = (*decrypt_input)(c);
1715 #endif
1716 		    if (c == 0) {
1717 			sbp++, scc--; count++;
1718 			/* a "true" CR */
1719 			TTYADD('\r');
1720 		    } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1721 					(c == '\n')) {
1722 			sbp++, scc--; count++;
1723 			TTYADD('\n');
1724 		    } else {
1725 #if    defined(ENCRYPTION)
1726 			if (decrypt_input)
1727 			    (*decrypt_input)(-1);
1728 #endif
1729 			TTYADD('\r');
1730 			if (crmod) {
1731 				TTYADD('\n');
1732 			}
1733 		    }
1734 		} else {
1735 		    telrcv_state = TS_CR;
1736 		    TTYADD('\r');
1737 		    if (crmod) {
1738 			    TTYADD('\n');
1739 		    }
1740 		}
1741 	    } else {
1742 		TTYADD(c);
1743 	    }
1744 	    continue;
1745 
1746 	case TS_IAC:
1747 process_iac:
1748 	    switch (c) {
1749 
1750 	    case WILL:
1751 		telrcv_state = TS_WILL;
1752 		continue;
1753 
1754 	    case WONT:
1755 		telrcv_state = TS_WONT;
1756 		continue;
1757 
1758 	    case DO:
1759 		telrcv_state = TS_DO;
1760 		continue;
1761 
1762 	    case DONT:
1763 		telrcv_state = TS_DONT;
1764 		continue;
1765 
1766 	    case DM:
1767 		    /*
1768 		     * We may have missed an urgent notification,
1769 		     * so make sure we flush whatever is in the
1770 		     * buffer currently.
1771 		     */
1772 		printoption("RCVD", IAC, DM);
1773 		SYNCHing = 1;
1774 		(void) ttyflush(1);
1775 		SYNCHing = stilloob();
1776 		settimer(gotDM);
1777 		break;
1778 
1779 	    case SB:
1780 		SB_CLEAR();
1781 		telrcv_state = TS_SB;
1782 		continue;
1783 
1784 #	    if defined(TN3270)
1785 	    case EOR:
1786 		if (In3270) {
1787 		    if (Ibackp == Ifrontp) {
1788 			Ibackp = Ifrontp = Ibuf;
1789 			ISend = 0;	/* should have been! */
1790 		    } else {
1791 			Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
1792 			ISend = 1;
1793 		    }
1794 		}
1795 		printoption("RCVD", IAC, EOR);
1796 		break;
1797 #	    endif /* defined(TN3270) */
1798 
1799 	    case IAC:
1800 #	    if !defined(TN3270)
1801 		TTYADD(IAC);
1802 #	    else /* !defined(TN3270) */
1803 		if (In3270) {
1804 		    *Ifrontp++ = IAC;
1805 		} else {
1806 		    TTYADD(IAC);
1807 		}
1808 #	    endif /* !defined(TN3270) */
1809 		break;
1810 
1811 	    case NOP:
1812 	    case GA:
1813 	    default:
1814 		printoption("RCVD", IAC, c);
1815 		break;
1816 	    }
1817 	    telrcv_state = TS_DATA;
1818 	    continue;
1819 
1820 	case TS_WILL:
1821 	    printoption("RCVD", WILL, c);
1822 	    willoption(c);
1823 	    SetIn3270();
1824 	    telrcv_state = TS_DATA;
1825 	    continue;
1826 
1827 	case TS_WONT:
1828 	    printoption("RCVD", WONT, c);
1829 	    wontoption(c);
1830 	    SetIn3270();
1831 	    telrcv_state = TS_DATA;
1832 	    continue;
1833 
1834 	case TS_DO:
1835 	    printoption("RCVD", DO, c);
1836 	    dooption(c);
1837 	    SetIn3270();
1838 	    if (c == TELOPT_NAWS) {
1839 		sendnaws();
1840 	    } else if (c == TELOPT_LFLOW) {
1841 		localflow = 1;
1842 		setcommandmode();
1843 		setconnmode(0);
1844 	    }
1845 	    telrcv_state = TS_DATA;
1846 	    continue;
1847 
1848 	case TS_DONT:
1849 	    printoption("RCVD", DONT, c);
1850 	    dontoption(c);
1851 	    flushline = 1;
1852 	    setconnmode(0);	/* set new tty mode (maybe) */
1853 	    SetIn3270();
1854 	    telrcv_state = TS_DATA;
1855 	    continue;
1856 
1857 	case TS_SB:
1858 	    if (c == IAC) {
1859 		telrcv_state = TS_SE;
1860 	    } else {
1861 		SB_ACCUM(c);
1862 	    }
1863 	    continue;
1864 
1865 	case TS_SE:
1866 	    if (c != SE) {
1867 		if (c != IAC) {
1868 		    /*
1869 		     * This is an error.  We only expect to get
1870 		     * "IAC IAC" or "IAC SE".  Several things may
1871 		     * have happend.  An IAC was not doubled, the
1872 		     * IAC SE was left off, or another option got
1873 		     * inserted into the suboption are all possibilities.
1874 		     * If we assume that the IAC was not doubled,
1875 		     * and really the IAC SE was left off, we could
1876 		     * get into an infinate loop here.  So, instead,
1877 		     * we terminate the suboption, and process the
1878 		     * partial suboption if we can.
1879 		     */
1880 		    SB_ACCUM(IAC);
1881 		    SB_ACCUM(c);
1882 		    subpointer -= 2;
1883 		    SB_TERM();
1884 
1885 		    printoption("In SUBOPTION processing, RCVD", IAC, c);
1886 		    suboption();	/* handle sub-option */
1887 		    SetIn3270();
1888 		    telrcv_state = TS_IAC;
1889 		    goto process_iac;
1890 		}
1891 		SB_ACCUM(c);
1892 		telrcv_state = TS_SB;
1893 	    } else {
1894 		SB_ACCUM(IAC);
1895 		SB_ACCUM(SE);
1896 		subpointer -= 2;
1897 		SB_TERM();
1898 		suboption();	/* handle sub-option */
1899 		SetIn3270();
1900 		telrcv_state = TS_DATA;
1901 	    }
1902 	}
1903     }
1904     if (count)
1905 	ring_consumed(&netiring, count);
1906     return returnValue||count;
1907 }
1908 
1909 static int bol = 1, local = 0;
1910 
1911     int
1912 rlogin_susp()
1913 {
1914     if (local) {
1915 	local = 0;
1916 	bol = 1;
1917 	command(0, "z\n", 2);
1918 	return(1);
1919     }
1920     return(0);
1921 }
1922 
1923     static int
1924 telsnd()
1925 {
1926     int tcc;
1927     int count;
1928     int returnValue = 0;
1929     unsigned char *tbp;
1930 
1931     tcc = 0;
1932     count = 0;
1933     while (NETROOM() > 2) {
1934 	int sc;
1935 	int c;
1936 
1937 	if (tcc == 0) {
1938 	    if (count) {
1939 		ring_consumed(&ttyiring, count);
1940 		returnValue = 1;
1941 		count = 0;
1942 	    }
1943 	    tbp = ttyiring.consume;
1944 	    tcc = ring_full_consecutive(&ttyiring);
1945 	    if (tcc == 0) {
1946 		break;
1947 	    }
1948 	}
1949 	c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
1950 	if (rlogin != _POSIX_VDISABLE) {
1951 		if (bol) {
1952 			bol = 0;
1953 			if (sc == rlogin) {
1954 				local = 1;
1955 				continue;
1956 			}
1957 		} else if (local) {
1958 			local = 0;
1959 			if (sc == '.' || c == termEofChar) {
1960 				bol = 1;
1961 				command(0, "close\n", 6);
1962 				continue;
1963 			}
1964 			if (sc == termSuspChar) {
1965 				bol = 1;
1966 				command(0, "z\n", 2);
1967 				continue;
1968 			}
1969 			if (sc == escape) {
1970 				command(0, (char *)tbp, tcc);
1971 				bol = 1;
1972 				count += tcc;
1973 				tcc = 0;
1974 				flushline = 1;
1975 				break;
1976 			}
1977 			if (sc != rlogin) {
1978 				++tcc;
1979 				--tbp;
1980 				--count;
1981 				c = sc = rlogin;
1982 			}
1983 		}
1984 		if ((sc == '\n') || (sc == '\r'))
1985 			bol = 1;
1986 	} else if (escape != _POSIX_VDISABLE && sc == escape) {
1987 	    /*
1988 	     * Double escape is a pass through of a single escape character.
1989 	     */
1990 	    if (tcc && strip(*tbp) == escape) {
1991 		tbp++;
1992 		tcc--;
1993 		count++;
1994 		bol = 0;
1995 	    } else {
1996 		command(0, (char *)tbp, tcc);
1997 		bol = 1;
1998 		count += tcc;
1999 		tcc = 0;
2000 		flushline = 1;
2001 		break;
2002 	    }
2003 	} else
2004 	    bol = 0;
2005 #ifdef	KLUDGELINEMODE
2006 	if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
2007 	    if (tcc > 0 && strip(*tbp) == echoc) {
2008 		tcc--; tbp++; count++;
2009 	    } else {
2010 		dontlecho = !dontlecho;
2011 		settimer(echotoggle);
2012 		setconnmode(0);
2013 		flushline = 1;
2014 		break;
2015 	    }
2016 	}
2017 #endif
2018 	if (sc != _POSIX_VDISABLE && MODE_LOCAL_CHARS(globalmode)) {
2019 	    if (TerminalSpecialChars(sc) == 0) {
2020 		bol = 1;
2021 		break;
2022 	    }
2023 	}
2024 	if (my_want_state_is_wont(TELOPT_BINARY)) {
2025 	    switch (c) {
2026 	    case '\n':
2027 		    /*
2028 		     * If we are in CRMOD mode (\r ==> \n)
2029 		     * on our local machine, then probably
2030 		     * a newline (unix) is CRLF (TELNET).
2031 		     */
2032 		if (MODE_LOCAL_CHARS(globalmode)) {
2033 		    NETADD('\r');
2034 		}
2035 		NETADD('\n');
2036 		bol = flushline = 1;
2037 		break;
2038 	    case '\r':
2039 		if (!crlf) {
2040 		    NET2ADD('\r', '\0');
2041 		} else {
2042 		    NET2ADD('\r', '\n');
2043 		}
2044 		bol = flushline = 1;
2045 		break;
2046 	    case IAC:
2047 		NET2ADD(IAC, IAC);
2048 		break;
2049 	    default:
2050 		NETADD(c);
2051 		break;
2052 	    }
2053 	} else if (c == IAC) {
2054 	    NET2ADD(IAC, IAC);
2055 	} else {
2056 	    NETADD(c);
2057 	}
2058     }
2059     if (count)
2060 	ring_consumed(&ttyiring, count);
2061     return returnValue||count;		/* Non-zero if we did anything */
2062 }
2063 
2064 /*
2065  * Scheduler()
2066  *
2067  * Try to do something.
2068  *
2069  * If we do something useful, return 1; else return 0.
2070  *
2071  */
2072 
2073 
2074     int
2075 Scheduler(block)
2076     int	block;			/* should we block in the select ? */
2077 {
2078 		/* One wants to be a bit careful about setting returnValue
2079 		 * to one, since a one implies we did some useful work,
2080 		 * and therefore probably won't be called to block next
2081 		 * time (TN3270 mode only).
2082 		 */
2083     int returnValue;
2084     int netin, netout, netex, ttyin, ttyout;
2085 
2086     /* Decide which rings should be processed */
2087 
2088     netout = ring_full_count(&netoring) &&
2089 	    (flushline ||
2090 		(my_want_state_is_wont(TELOPT_LINEMODE)
2091 #ifdef	KLUDGELINEMODE
2092 			&& (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
2093 #endif
2094 		) ||
2095 			my_want_state_is_will(TELOPT_BINARY));
2096     ttyout = ring_full_count(&ttyoring);
2097 
2098 #if	defined(TN3270)
2099     ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0);
2100 #else	/* defined(TN3270) */
2101     ttyin = ring_empty_count(&ttyiring) && (clienteof == 0);
2102 #endif	/* defined(TN3270) */
2103 
2104 #if	defined(TN3270)
2105     netin = ring_empty_count(&netiring);
2106 #   else /* !defined(TN3270) */
2107     netin = !ISend && ring_empty_count(&netiring);
2108 #   endif /* !defined(TN3270) */
2109 
2110     netex = !SYNCHing;
2111 
2112     /* If we have seen a signal recently, reset things */
2113 #   if defined(TN3270) && defined(unix)
2114     if (HaveInput) {
2115 	HaveInput = 0;
2116 	(void) signal(SIGIO, inputAvailable);
2117     }
2118 #endif	/* defined(TN3270) && defined(unix) */
2119 
2120     /* Call to system code to process rings */
2121 
2122     returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
2123 
2124     /* Now, look at the input rings, looking for work to do. */
2125 
2126     if (ring_full_count(&ttyiring)) {
2127 #   if defined(TN3270)
2128 	if (In3270) {
2129 	    int c;
2130 
2131 	    c = DataFromTerminal(ttyiring.consume,
2132 					ring_full_consecutive(&ttyiring));
2133 	    if (c) {
2134 		returnValue = 1;
2135 		ring_consumed(&ttyiring, c);
2136 	    }
2137 	} else {
2138 #   endif /* defined(TN3270) */
2139 	    returnValue |= telsnd();
2140 #   if defined(TN3270)
2141 	}
2142 #   endif /* defined(TN3270) */
2143     }
2144 
2145     if (ring_full_count(&netiring)) {
2146 #	if !defined(TN3270)
2147 	returnValue |= telrcv();
2148 #	else /* !defined(TN3270) */
2149 	returnValue = Push3270();
2150 #	endif /* !defined(TN3270) */
2151     }
2152     return returnValue;
2153 }
2154 
2155 /*
2156  * Select from tty and network...
2157  */
2158     void
2159 telnet(user)
2160     char *user;
2161 {
2162     sys_telnet_init();
2163 
2164 #if	defined(AUTHENTICATION) || defined(ENCRYPTION)
2165     {
2166 	static char local_host[256] = { 0 };
2167 
2168 	if (!local_host[0]) {
2169 		gethostname(local_host, sizeof(local_host));
2170 		local_host[sizeof(local_host)-1] = 0;
2171 	}
2172 	auth_encrypt_init(local_host, hostname, "TELNET", 0);
2173 	auth_encrypt_user(user);
2174     }
2175 #endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
2176 #   if !defined(TN3270)
2177     if (telnetport) {
2178 #if	defined(AUTHENTICATION)
2179 	if (autologin)
2180 		send_will(TELOPT_AUTHENTICATION, 1);
2181 #endif
2182 #if    defined(ENCRYPTION)
2183 	send_do(TELOPT_ENCRYPT, 1);
2184 	send_will(TELOPT_ENCRYPT, 1);
2185 #endif
2186 	send_do(TELOPT_SGA, 1);
2187 	send_will(TELOPT_TTYPE, 1);
2188 	send_will(TELOPT_NAWS, 1);
2189 	send_will(TELOPT_TSPEED, 1);
2190 	send_will(TELOPT_LFLOW, 1);
2191 	send_will(TELOPT_LINEMODE, 1);
2192 	send_will(TELOPT_NEW_ENVIRON, 1);
2193 	send_do(TELOPT_STATUS, 1);
2194 	if (env_getvalue((unsigned char *)"DISPLAY"))
2195 	    send_will(TELOPT_XDISPLOC, 1);
2196 	if (binary)
2197 	    tel_enter_binary(binary);
2198     }
2199 #   endif /* !defined(TN3270) */
2200 
2201 #   if !defined(TN3270)
2202     for (;;) {
2203 	int schedValue;
2204 
2205 	while ((schedValue = Scheduler(0)) != 0) {
2206 	    if (schedValue == -1) {
2207 		setcommandmode();
2208 		return;
2209 	    }
2210 	}
2211 
2212 	if (Scheduler(1) == -1) {
2213 	    setcommandmode();
2214 	    return;
2215 	}
2216     }
2217 #   else /* !defined(TN3270) */
2218     for (;;) {
2219 	int schedValue;
2220 
2221 	while (!In3270 && !shell_active) {
2222 	    if (Scheduler(1) == -1) {
2223 		setcommandmode();
2224 		return;
2225 	    }
2226 	}
2227 
2228 	while ((schedValue = Scheduler(0)) != 0) {
2229 	    if (schedValue == -1) {
2230 		setcommandmode();
2231 		return;
2232 	    }
2233 	}
2234 		/* If there is data waiting to go out to terminal, don't
2235 		 * schedule any more data for the terminal.
2236 		 */
2237 	if (ring_full_count(&ttyoring)) {
2238 	    schedValue = 1;
2239 	} else {
2240 	    if (shell_active) {
2241 		if (shell_continue() == 0) {
2242 		    ConnectScreen();
2243 		}
2244 	    } else if (In3270) {
2245 		schedValue = DoTerminalOutput();
2246 	    }
2247 	}
2248 	if (schedValue && (shell_active == 0)) {
2249 	    if (Scheduler(1) == -1) {
2250 		setcommandmode();
2251 		return;
2252 	    }
2253 	}
2254     }
2255 #   endif /* !defined(TN3270) */
2256 }
2257 
2258 #if	0	/* XXX - this not being in is a bug */
2259 /*
2260  * nextitem()
2261  *
2262  *	Return the address of the next "item" in the TELNET data
2263  * stream.  This will be the address of the next character if
2264  * the current address is a user data character, or it will
2265  * be the address of the character following the TELNET command
2266  * if the current address is a TELNET IAC ("I Am a Command")
2267  * character.
2268  */
2269 
2270     static char *
2271 nextitem(current)
2272     char *current;
2273 {
2274     if ((*current&0xff) != IAC) {
2275 	return current+1;
2276     }
2277     switch (*(current+1)&0xff) {
2278     case DO:
2279     case DONT:
2280     case WILL:
2281     case WONT:
2282 	return current+3;
2283     case SB:		/* loop forever looking for the SE */
2284 	{
2285 	    char *look = current+2;
2286 
2287 	    for (;;) {
2288 		if ((*look++&0xff) == IAC) {
2289 		    if ((*look++&0xff) == SE) {
2290 			return look;
2291 		    }
2292 		}
2293 	    }
2294 	}
2295     default:
2296 	return current+2;
2297     }
2298 }
2299 #endif	/* 0 */
2300 
2301 /*
2302  * netclear()
2303  *
2304  *	We are about to do a TELNET SYNCH operation.  Clear
2305  * the path to the network.
2306  *
2307  *	Things are a bit tricky since we may have sent the first
2308  * byte or so of a previous TELNET command into the network.
2309  * So, we have to scan the network buffer from the beginning
2310  * until we are up to where we want to be.
2311  *
2312  *	A side effect of what we do, just to keep things
2313  * simple, is to clear the urgent data pointer.  The principal
2314  * caller should be setting the urgent data pointer AFTER calling
2315  * us in any case.
2316  */
2317 
2318     static void
2319 netclear()
2320 {
2321 #if	0	/* XXX */
2322     char *thisitem, *next;
2323     char *good;
2324 #define	wewant(p)	((nfrontp > p) && ((*p&0xff) == IAC) && \
2325 				((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
2326 
2327     thisitem = netobuf;
2328 
2329     while ((next = nextitem(thisitem)) <= netobuf.send) {
2330 	thisitem = next;
2331     }
2332 
2333     /* Now, thisitem is first before/at boundary. */
2334 
2335     good = netobuf;	/* where the good bytes go */
2336 
2337     while (netoring.add > thisitem) {
2338 	if (wewant(thisitem)) {
2339 	    int length;
2340 
2341 	    next = thisitem;
2342 	    do {
2343 		next = nextitem(next);
2344 	    } while (wewant(next) && (nfrontp > next));
2345 	    length = next-thisitem;
2346 	    memmove(good, thisitem, length);
2347 	    good += length;
2348 	    thisitem = next;
2349 	} else {
2350 	    thisitem = nextitem(thisitem);
2351 	}
2352     }
2353 
2354 #endif	/* 0 */
2355 }
2356 
2357 /*
2358  * These routines add various telnet commands to the data stream.
2359  */
2360 
2361     static void
2362 doflush()
2363 {
2364     NET2ADD(IAC, DO);
2365     NETADD(TELOPT_TM);
2366     flushline = 1;
2367     flushout = 1;
2368     (void) ttyflush(1);			/* Flush/drop output */
2369     /* do printoption AFTER flush, otherwise the output gets tossed... */
2370     printoption("SENT", DO, TELOPT_TM);
2371 }
2372 
2373     void
2374 xmitAO()
2375 {
2376     NET2ADD(IAC, AO);
2377     printoption("SENT", IAC, AO);
2378     if (autoflush) {
2379 	doflush();
2380     }
2381 }
2382 
2383 
2384     void
2385 xmitEL()
2386 {
2387     NET2ADD(IAC, EL);
2388     printoption("SENT", IAC, EL);
2389 }
2390 
2391     void
2392 xmitEC()
2393 {
2394     NET2ADD(IAC, EC);
2395     printoption("SENT", IAC, EC);
2396 }
2397 
2398 
2399     int
2400 dosynch()
2401 {
2402     netclear();			/* clear the path to the network */
2403     NETADD(IAC);
2404     setneturg();
2405     NETADD(DM);
2406     printoption("SENT", IAC, DM);
2407     return 1;
2408 }
2409 
2410 int want_status_response = 0;
2411 
2412     int
2413 get_status()
2414 {
2415     unsigned char tmp[16];
2416     unsigned char *cp;
2417 
2418     if (my_want_state_is_dont(TELOPT_STATUS)) {
2419 	printf("Remote side does not support STATUS option\n");
2420 	return 0;
2421     }
2422     cp = tmp;
2423 
2424     *cp++ = IAC;
2425     *cp++ = SB;
2426     *cp++ = TELOPT_STATUS;
2427     *cp++ = TELQUAL_SEND;
2428     *cp++ = IAC;
2429     *cp++ = SE;
2430     if (NETROOM() >= cp - tmp) {
2431 	ring_supply_data(&netoring, tmp, cp-tmp);
2432 	printsub('>', tmp+2, cp - tmp - 2);
2433     }
2434     ++want_status_response;
2435     return 1;
2436 }
2437 
2438     void
2439 intp()
2440 {
2441     NET2ADD(IAC, IP);
2442     printoption("SENT", IAC, IP);
2443     flushline = 1;
2444     if (autoflush) {
2445 	doflush();
2446     }
2447     if (autosynch) {
2448 	dosynch();
2449     }
2450 }
2451 
2452     void
2453 sendbrk()
2454 {
2455     NET2ADD(IAC, BREAK);
2456     printoption("SENT", IAC, BREAK);
2457     flushline = 1;
2458     if (autoflush) {
2459 	doflush();
2460     }
2461     if (autosynch) {
2462 	dosynch();
2463     }
2464 }
2465 
2466     void
2467 sendabort()
2468 {
2469     NET2ADD(IAC, ABORT);
2470     printoption("SENT", IAC, ABORT);
2471     flushline = 1;
2472     if (autoflush) {
2473 	doflush();
2474     }
2475     if (autosynch) {
2476 	dosynch();
2477     }
2478 }
2479 
2480     void
2481 sendsusp()
2482 {
2483     NET2ADD(IAC, SUSP);
2484     printoption("SENT", IAC, SUSP);
2485     flushline = 1;
2486     if (autoflush) {
2487 	doflush();
2488     }
2489     if (autosynch) {
2490 	dosynch();
2491     }
2492 }
2493 
2494     void
2495 sendeof()
2496 {
2497     NET2ADD(IAC, xEOF);
2498     printoption("SENT", IAC, xEOF);
2499 }
2500 
2501     void
2502 sendayt()
2503 {
2504     NET2ADD(IAC, AYT);
2505     printoption("SENT", IAC, AYT);
2506 }
2507 
2508 /*
2509  * Send a window size update to the remote system.
2510  */
2511 
2512     void
2513 sendnaws()
2514 {
2515     long rows, cols;
2516     unsigned char tmp[16];
2517     unsigned char *cp;
2518 
2519     if (my_state_is_wont(TELOPT_NAWS))
2520 	return;
2521 
2522 #define	PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2523 			    if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2524 
2525     if (TerminalWindowSize(&rows, &cols) == 0) {	/* Failed */
2526 	return;
2527     }
2528 
2529     cp = tmp;
2530 
2531     *cp++ = IAC;
2532     *cp++ = SB;
2533     *cp++ = TELOPT_NAWS;
2534     PUTSHORT(cp, cols);
2535     PUTSHORT(cp, rows);
2536     *cp++ = IAC;
2537     *cp++ = SE;
2538     if (NETROOM() >= cp - tmp) {
2539 	ring_supply_data(&netoring, tmp, cp-tmp);
2540 	printsub('>', tmp+2, cp - tmp - 2);
2541     }
2542 }
2543 
2544     void
2545 tel_enter_binary(rw)
2546     int rw;
2547 {
2548     if (rw&1)
2549 	send_do(TELOPT_BINARY, 1);
2550     if (rw&2)
2551 	send_will(TELOPT_BINARY, 1);
2552 }
2553 
2554     void
2555 tel_leave_binary(rw)
2556     int rw;
2557 {
2558     if (rw&1)
2559 	send_dont(TELOPT_BINARY, 1);
2560     if (rw&2)
2561 	send_wont(TELOPT_BINARY, 1);
2562 }
2563