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