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