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