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