xref: /csrg-svn/usr.bin/telnet/telnet.c (revision 42770)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)telnet.c	5.47 (Berkeley) 06/01/90";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 
14 #if	defined(unix)
15 #include <signal.h>
16 /* By the way, we need to include curses.h before telnet.h since,
17  * among other things, telnet.h #defines 'DO', which is a variable
18  * declared in curses.h.
19  */
20 #endif	/* defined(unix) */
21 
22 #include <arpa/telnet.h>
23 
24 #include <string.h>
25 
26 #include <ctype.h>
27 
28 #include "ring.h"
29 
30 #include "defines.h"
31 #include "externs.h"
32 #include "types.h"
33 #include "general.h"
34 
35 
36 #define	strip(x)	((x)&0x7f)
37 
38 
39 static char	subbuffer[SUBBUFSIZE],
40 		*subpointer, *subend;	 /* buffer for sub-options */
41 #define	SB_CLEAR()	subpointer = subbuffer;
42 #define	SB_TERM()	subend = subpointer;
43 #define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \
44 				*subpointer++ = (c); \
45 			}
46 
47 char	options[256];		/* The combined options */
48 char	do_dont_resp[256];
49 char	will_wont_resp[256];
50 
51 int
52 	connected,
53 	showoptions,
54 	In3270,		/* Are we in 3270 mode? */
55 	ISend,		/* trying to send network data in */
56 	debug = 0,
57 	crmod,
58 	netdata,	/* Print out network data flow */
59 	crlf,		/* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
60 #if	defined(TN3270)
61 	noasynchtty = 0,/* User specified "-noasynch" on command line */
62 	noasynchnet = 0,/* User specified "-noasynch" on command line */
63 	askedSGA = 0,	/* We have talked about suppress go ahead */
64 #endif	/* defined(TN3270) */
65 	telnetport,
66 	SYNCHing,	/* we are in TELNET SYNCH mode */
67 	flushout,	/* flush output */
68 	autoflush = 0,	/* flush output when interrupting? */
69 	autosynch,	/* send interrupt characters with SYNCH? */
70 	localflow,	/* we handle flow control locally */
71 	localchars,	/* we recognize interrupt/quit */
72 	donelclchars,	/* the user has set "localchars" */
73 	donebinarytoggle,	/* the user has put us in binary */
74 	dontlecho,	/* do we suppress local echoing right now? */
75 	globalmode;
76 
77 #define	CONTROL(x)	((x)&0x1f)		/* CTRL(x) is not portable */
78 
79 unsigned char *prompt = 0;
80 
81 cc_t escape, echoc;
82 
83 /*
84  * Telnet receiver states for fsm
85  */
86 #define	TS_DATA		0
87 #define	TS_IAC		1
88 #define	TS_WILL		2
89 #define	TS_WONT		3
90 #define	TS_DO		4
91 #define	TS_DONT		5
92 #define	TS_CR		6
93 #define	TS_SB		7		/* sub-option collection */
94 #define	TS_SE		8		/* looking for sub-option end */
95 
96 static int	telrcv_state;
97 
98 jmp_buf	toplevel = { 0 };
99 jmp_buf	peerdied;
100 
101 int	flushline;
102 int	linemode;
103 
104 #ifdef	KLUDGELINEMODE
105 int	kludgelinemode = 1;
106 #endif
107 
108 /*
109  * The following are some clocks used to decide how to interpret
110  * the relationship between various variables.
111  */
112 
113 Clocks clocks;
114 
115 #ifdef	notdef
116 Modelist modelist[] = {
117 	{ "telnet command mode", COMMAND_LINE },
118 	{ "character-at-a-time mode", 0 },
119 	{ "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
120 	{ "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
121 	{ "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
122 	{ "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
123 	{ "3270 mode", 0 },
124 };
125 #endif
126 
127 
128 /*
129  * Initialize telnet environment.
130  */
131 
132 init_telnet()
133 {
134     SB_CLEAR();
135     ClearArray(options);
136 
137     connected = In3270 = ISend = localflow = donebinarytoggle = 0;
138 
139     SYNCHing = 0;
140 
141     /* Don't change NetTrace */
142 
143     escape = CONTROL(']');
144     echoc = CONTROL('E');
145 
146     flushline = 1;
147     telrcv_state = TS_DATA;
148 }
149 
150 
151 #include <varargs.h>
152 
153 /*VARARGS*/
154 static void
155 printring(va_alist)
156 va_dcl
157 {
158     va_list ap;
159     char buffer[100];		/* where things go */
160     char *ptr;
161     char *format;
162     char *string;
163     Ring *ring;
164     int i;
165 
166     va_start(ap);
167 
168     ring = va_arg(ap, Ring *);
169     format = va_arg(ap, char *);
170     ptr = buffer;
171 
172     while ((i = *format++) != 0) {
173 	if (i == '%') {
174 	    i = *format++;
175 	    switch (i) {
176 	    case 'c':
177 		*ptr++ = va_arg(ap, int);
178 		break;
179 	    case 's':
180 		string = va_arg(ap, char *);
181 		ring_supply_data(ring, buffer, ptr-buffer);
182 		ring_supply_data(ring, string, strlen(string));
183 		ptr = buffer;
184 		break;
185 	    case 0:
186 		ExitString("printring: trailing %%.\n", 1);
187 		/*NOTREACHED*/
188 	    default:
189 		ExitString("printring: unknown format character.\n", 1);
190 		/*NOTREACHED*/
191 	    }
192 	} else {
193 	    *ptr++ = i;
194 	}
195     }
196     ring_supply_data(ring, buffer, ptr-buffer);
197 }
198 
199 /*
200  * These routines are in charge of sending option negotiations
201  * to the other side.
202  *
203  * The basic idea is that we send the negotiation if either side
204  * is in disagreement as to what the current state should be.
205  */
206 
207 send_do(c, init)
208 register int c, init;
209 {
210     if (init) {
211 	if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
212 				my_want_state_is_do(c))
213 	    return;
214 	set_my_want_state_do(c);
215 	do_dont_resp[c]++;
216     }
217     NET2ADD(IAC, DO);
218     NETADD(c);
219     printoption("SENT", "do", c);
220 }
221 
222 void
223 send_dont(c, init)
224 register int c, init;
225 {
226     if (init) {
227 	if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
228 				my_want_state_is_dont(c))
229 	    return;
230 	set_my_want_state_dont(c);
231 	do_dont_resp[c]++;
232     }
233     NET2ADD(IAC, DONT);
234     NETADD(c);
235     printoption("SENT", "dont", c);
236 }
237 
238 void
239 send_will(c, init)
240 register int c, init;
241 {
242     if (init) {
243 	if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
244 				my_want_state_is_will(c))
245 	    return;
246 	set_my_want_state_will(c);
247 	will_wont_resp[c]++;
248     }
249     NET2ADD(IAC, WILL);
250     NETADD(c);
251     printoption("SENT", "will", c);
252 }
253 
254 void
255 send_wont(c, init)
256 register int c, init;
257 {
258     if (init) {
259 	if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
260 				my_want_state_is_wont(c))
261 	    return;
262 	set_my_want_state_wont(c);
263 	will_wont_resp[c]++;
264     }
265     NET2ADD(IAC, WONT);
266     NETADD(c);
267     printoption("SENT", "wont", c);
268 }
269 
270 
271 void
272 willoption(option)
273 	int option;
274 {
275 	char *fmt;
276 	int new_state_ok = 0;
277 
278 	if (do_dont_resp[option]) {
279 	    --do_dont_resp[option];
280 	    if (do_dont_resp[option] && my_state_is_do(option))
281 		--do_dont_resp[option];
282 	}
283 
284 	if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
285 
286 	    switch (option) {
287 
288 	    case TELOPT_ECHO:
289 #	    if defined(TN3270)
290 		/*
291 		 * The following is a pain in the rear-end.
292 		 * Various IBM servers (some versions of Wiscnet,
293 		 * possibly Fibronics/Spartacus, and who knows who
294 		 * else) will NOT allow us to send "DO SGA" too early
295 		 * in the setup proceedings.  On the other hand,
296 		 * 4.2 servers (telnetd) won't set SGA correctly.
297 		 * So, we are stuck.  Empirically (but, based on
298 		 * a VERY small sample), the IBM servers don't send
299 		 * out anything about ECHO, so we postpone our sending
300 		 * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
301 		 * DO send).
302 		  */
303 		{
304 		    if (askedSGA == 0) {
305 			askedSGA = 1;
306 			if (my_want_state_is_dont(TELOPT_SGA))
307 			    send_do(TELOPT_SGA, 1);
308 		    }
309 		}
310 		    /* Fall through */
311 	    case TELOPT_EOR:
312 #endif	    /* defined(TN3270) */
313 	    case TELOPT_BINARY:
314 	    case TELOPT_SGA:
315 		settimer(modenegotiated);
316 		/* FALL THROUGH */
317 	    case TELOPT_STATUS:
318 		new_state_ok = 1;
319 		break;
320 
321 	    case TELOPT_TM:
322 		if (flushout)
323 		    flushout = 0;
324 		/*
325 		 * Special case for TM.  If we get back a WILL,
326 		 * pretend we got back a WONT.
327 		 */
328 		set_my_want_state_dont(option);
329 		set_my_state_dont(option);
330 		return;			/* Never reply to TM will's/wont's */
331 
332 	    case TELOPT_LINEMODE:
333 	    default:
334 		break;
335 	    }
336 
337 	    if (new_state_ok) {
338 		set_my_want_state_do(option);
339 		send_do(option, 0);
340 		setconnmode(0);		/* possibly set new tty mode */
341 	    } else {
342 		do_dont_resp[option]++;
343 		send_dont(option, 0);
344 	    }
345 	}
346 	set_my_state_do(option);
347 }
348 
349 void
350 wontoption(option)
351 	int option;
352 {
353 	char *fmt;
354 
355 	if (do_dont_resp[option]) {
356 	    --do_dont_resp[option];
357 	    if (do_dont_resp[option] && my_state_is_dont(option))
358 		--do_dont_resp[option];
359 	}
360 
361 	if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
362 
363 	    switch (option) {
364 
365 #ifdef	KLUDGELINEMODE
366 	    case TELOPT_SGA:
367 		if (!kludgelinemode)
368 		    break;
369 		/* FALL THROUGH */
370 #endif
371 	    case TELOPT_ECHO:
372 		settimer(modenegotiated);
373 		break;
374 
375 	    case TELOPT_TM:
376 		if (flushout)
377 		    flushout = 0;
378 		set_my_want_state_dont(option);
379 		set_my_state_dont(option);
380 		return;		/* Never reply to TM will's/wont's */
381 
382 	    default:
383 		break;
384 	    }
385 	    set_my_want_state_dont(option);
386 	    send_dont(option, 0);
387 	    setconnmode(0);			/* Set new tty mode */
388 	} else if (option == TELOPT_TM) {
389 	    /*
390 	     * Special case for TM.
391 	     */
392 	    if (flushout)
393 		flushout = 0;
394 	    set_my_want_state_dont(option);
395 	}
396 	set_my_state_dont(option);
397 }
398 
399 static void
400 dooption(option)
401 	int option;
402 {
403 	char *fmt;
404 	int new_state_ok = 0;
405 
406 	if (will_wont_resp[option]) {
407 	    --will_wont_resp[option];
408 	    if (will_wont_resp[option] && my_state_is_will(option))
409 		--will_wont_resp[option];
410 	}
411 
412 	if (will_wont_resp[option] == 0) {
413 	  if (my_want_state_is_wont(option)) {
414 
415 	    switch (option) {
416 
417 	    case TELOPT_TM:
418 		/*
419 		 * Special case for TM.  We send a WILL, but pretend
420 		 * we sent WONT.
421 		 */
422 		send_will(option, 0);
423 		set_my_want_state_wont(TELOPT_TM);
424 		set_my_state_wont(TELOPT_TM);
425 		return;
426 
427 #	if defined(TN3270)
428 	    case TELOPT_EOR:		/* end of record */
429 #	endif	/* defined(TN3270) */
430 	    case TELOPT_BINARY:		/* binary mode */
431 	    case TELOPT_NAWS:		/* window size */
432 	    case TELOPT_TSPEED:		/* terminal speed */
433 	    case TELOPT_LFLOW:		/* local flow control */
434 	    case TELOPT_TTYPE:		/* terminal type option */
435 	    case TELOPT_SGA:		/* no big deal */
436 		new_state_ok = 1;
437 		break;
438 
439 	    case TELOPT_LINEMODE:
440 #ifdef	KLUDGELINEMODE
441 		kludgelinemode = 0;
442 #endif
443 		set_my_want_state_will(TELOPT_LINEMODE);
444 		send_will(option, 0);
445 		set_my_state_will(TELOPT_LINEMODE);
446 		slc_init();
447 		return;
448 
449 	    case TELOPT_ECHO:		/* We're never going to echo... */
450 	    default:
451 		break;
452 	    }
453 
454 	    if (new_state_ok) {
455 		set_my_want_state_will(option);
456 		send_will(option, 0);
457 	    } else {
458 		will_wont_resp[option]++;
459 		send_wont(option, 0);
460 	    }
461 	  } else {
462 	    /*
463 	     * Handle options that need more things done after the
464 	     * other side has acknowledged the option.
465 	     */
466 	    switch (option) {
467 	    case TELOPT_LINEMODE:
468 #ifdef	KLUDGELINEMODE
469 		kludgelinemode = 0;
470 #endif
471 		set_my_state_will(option);
472 		slc_init();
473 		return;
474 	    }
475 	  }
476 	}
477 	set_my_state_will(option);
478 }
479 
480 static void
481 dontoption(option)
482 	int option;
483 {
484 
485 	if (will_wont_resp[option]) {
486 	    --will_wont_resp[option];
487 	    if (will_wont_resp[option] && my_state_is_wont(option))
488 		--will_wont_resp[option];
489 	}
490 
491 	if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
492 	    switch (option) {
493 	    case TELOPT_LINEMODE:
494 		linemode = 0;	/* put us back to the default state */
495 		break;
496 	    }
497 	    /* we always accept a DONT */
498 	    set_my_want_state_wont(option);
499 	    send_wont(option, 0);
500 	    setconnmode(0);			/* Set new tty mode */
501 	}
502 	set_my_state_wont(option);
503 }
504 
505 /*
506  * Given a buffer returned by tgetent(), this routine will turn
507  * the pipe seperated list of names in the buffer into an array
508  * of pointers to null terminated names.  We toss out any bad,
509  * duplicate, or verbose names (names with spaces).
510  */
511 
512 static char *unknown[] = { "UNKNOWN", 0 };
513 
514 char **
515 mklist(buf, name)
516 char *buf, *name;
517 {
518 	register int n;
519 	register char c, *cp, **argvp, *cp2, **argv;
520 	char *malloc();
521 
522 	if (name) {
523 		if (strlen(name) > 40)
524 			name = 0;
525 		else {
526 			unknown[0] = name;
527 			upcase(name);
528 		}
529 	}
530 	/*
531 	 * Count up the number of names.
532 	 */
533 	for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
534 		if (*cp == '|')
535 			n++;
536 	}
537 	/*
538 	 * Allocate an array to put the name pointers into
539 	 */
540 	argv = (char **)malloc((n+3)*sizeof(char *));
541 	if (argv == 0)
542 		return(unknown);
543 
544 	/*
545 	 * Fill up the array of pointers to names.
546 	 */
547 	*argv = 0;
548 	argvp = argv+1;
549 	n = 0;
550 	for (cp = cp2 = buf; (c = *cp);  cp++) {
551 		if (c == '|' || c == ':') {
552 			*cp++ = '\0';
553 			/*
554 			 * Skip entries that have spaces or are over 40
555 			 * characters long.  If this is our environment
556 			 * name, then put it up front.  Otherwise, as
557 			 * long as this is not a duplicate name (case
558 			 * insensitive) add it to the list.
559 			 */
560 			if (n || (cp - cp2 > 41))
561 				;
562 			else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
563 				*argv = cp2;
564 			else if (is_unique(cp2, argv+1, argvp))
565 				*argvp++ = cp2;
566 			if (c == ':')
567 				break;
568 			/*
569 			 * Skip multiple delimiters. Reset cp2 to
570 			 * the beginning of the next name. Reset n,
571 			 * the flag for names with spaces.
572 			 */
573 			while ((c = *cp) == '|')
574 				cp++;
575 			cp2 = cp;
576 			n = 0;
577 		}
578 		/*
579 		 * Skip entries with spaces or non-ascii values.
580 		 * Convert lower case letters to upper case.
581 		 */
582 		if ((c == ' ') || !isascii(c))
583 			n = 1;
584 		else if (islower(c))
585 			*cp = toupper(c);
586 	}
587 
588 	/*
589 	 * Check for an old V6 2 character name.  If the second
590 	 * name points to the beginning of the buffer, and is
591 	 * only 2 characters long, move it to the end of the array.
592 	 */
593 	if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
594 		*argvp++ = buf;
595 		cp = *argv++;
596 		*argv = cp;
597 	}
598 
599 	/*
600 	 * Duplicate last name, for TTYPE option, and null
601 	 * terminate the array.  If we didn't find a match on
602 	 * our terminal name, put that name at the beginning.
603 	 */
604 	cp = *(argvp-1);
605 	*argvp++ = cp;
606 	*argvp = 0;
607 
608 	if (*argv == 0) {
609 		if (name)
610 			*argv = name;
611 		else
612 			argv++;
613 	}
614 	if (*argv)
615 		return(argv);
616 	else
617 		return(unknown);
618 }
619 
620 is_unique(name, as, ae)
621 register char *name, **as, **ae;
622 {
623 	register char **ap;
624 	register int n;
625 
626 	n = strlen(name) + 1;
627 	for (ap = as; ap < ae; ap++)
628 		if (strncasecmp(*ap, name, n) == 0)
629 			return(0);
630 	return (1);
631 }
632 
633 #ifdef	TERMCAP
634 char termbuf[1024];
635 setupterm(tname, fd, errp)
636 char *tname;
637 int fd, *errp;
638 {
639 	if (tgetent(termbuf, tname) == 1) {
640 		termbuf[1023] = '\0';
641 		if (errp)
642 			*errp = 1;
643 		return(0);
644 	}
645 	if (errp)
646 		*errp = 0;
647 	return(-1);
648 }
649 #else
650 #define	termbuf	ttytype
651 extern char ttytype[];
652 #endif
653 
654 char *
655 gettermname()
656 {
657 	char *tname;
658 	static int first = 1;
659 	static char **tnamep;
660 	static char **next;
661 	char *getenv();
662 	int err;
663 
664 	if (first) {
665 		first = 0;
666 		if ((tname = getenv("TERM")) &&
667 				(setupterm(tname, 1, &err) == 0)) {
668 			tnamep = mklist(termbuf, tname);
669 		} else {
670 			if (tname && (strlen(tname) <= 40)) {
671 				unknown[0] = tname;
672 				upcase(tname);
673 			}
674 			tnamep = unknown;
675 		}
676 		next = tnamep;
677 	}
678 	if (*next == 0)
679 		next = tnamep;
680 	return(*next++);
681 }
682 /*
683  * suboption()
684  *
685  *	Look at the sub-option buffer, and try to be helpful to the other
686  * side.
687  *
688  *	Currently we recognize:
689  *
690  *		Terminal type, send request.
691  *		Terminal speed (send request).
692  *		Local flow control (is request).
693  *		Linemode
694  */
695 
696 static void
697 suboption()
698 {
699     printsub('<', subbuffer, subend-subbuffer+2);
700     switch (subbuffer[0]&0xff) {
701     case TELOPT_TTYPE:
702 	if (my_want_state_is_wont(TELOPT_TTYPE))
703 	    return;
704 	if ((subbuffer[1]&0xff) != TELQUAL_SEND) {
705 	    ;
706 	} else {
707 	    char *name;
708 	    extern char *getenv();
709 	    char temp[50];
710 	    int len;
711 
712 #if	defined(TN3270)
713 	    if (tn3270_ttype()) {
714 		return;
715 	    }
716 #endif	/* defined(TN3270) */
717 	    name = gettermname();
718 	    len = strlen(name) + 4 + 2;
719 	    if (len < NETROOM()) {
720 		sprintf(temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
721 				TELQUAL_IS, name, IAC, SE);
722 		ring_supply_data(&netoring, temp, len);
723 		printsub('>', &temp[2], len-2);
724 	    } else {
725 		ExitString("No room in buffer for terminal type.\n", 1);
726 		/*NOTREACHED*/
727 	    }
728 	}
729 	break;
730     case TELOPT_TSPEED:
731 	if (my_want_state_is_wont(TELOPT_TSPEED))
732 	    return;
733 	if ((subbuffer[1]&0xff) == TELQUAL_SEND) {
734 	    long ospeed,ispeed;
735 	    char temp[50];
736 	    int len;
737 
738 	    TerminalSpeeds(&ispeed, &ospeed);
739 
740 	    sprintf(temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED,
741 		    TELQUAL_IS, ospeed, ispeed, IAC, SE);
742 	    len = strlen(temp+4) + 4;	/* temp[3] is 0 ... */
743 
744 	    if (len < NETROOM()) {
745 		ring_supply_data(&netoring, temp, len);
746 		printsub('>', temp+2, len - 2);
747 	    }
748 	}
749 	break;
750     case TELOPT_LFLOW:
751 	if (my_want_state_is_wont(TELOPT_LFLOW))
752 	    return;
753 	if ((subbuffer[1]&0xff) == 1) {
754 	    localflow = 1;
755 	} else if ((subbuffer[1]&0xff) == 0) {
756 	    localflow = 0;
757 	}
758 	setcommandmode();
759 	setconnmode(0);
760 	break;
761 
762     case TELOPT_LINEMODE:
763 	if (my_want_state_is_wont(TELOPT_LINEMODE))
764 	    return;
765 	switch (subbuffer[1]&0xff) {
766 	case WILL:
767 	    lm_will(&subbuffer[2], subend - &subbuffer[2]);
768 	    break;
769 	case WONT:
770 	    lm_wont(&subbuffer[2], subend - &subbuffer[2]);
771 	    break;
772 	case DO:
773 	    lm_do(&subbuffer[2], subend - &subbuffer[2]);
774 	    break;
775 	case DONT:
776 	    lm_dont(&subbuffer[2], subend - &subbuffer[2]);
777 	    break;
778 	case LM_SLC:
779 	    slc(&subbuffer[2], subend - &subbuffer[2]);
780 	    break;
781 	case LM_MODE:
782 	    lm_mode(&subbuffer[2], subend - &subbuffer[2], 0);
783 	    break;
784 	default:
785 		break;
786 	}
787 	break;
788     default:
789 	break;
790     }
791 }
792 
793 static char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
794 
795 lm_will(cmd, len)
796 char *cmd;
797 {
798     switch(cmd[0]) {
799     case LM_FORWARDMASK:	/* We shouldn't ever get this... */
800     default:
801 	str_lm[3] = DONT;
802 	str_lm[4] = cmd[0];
803 	if (NETROOM() > sizeof(str_lm)) {
804 	    ring_supply_data(&netoring, str_lm, sizeof(str_lm));
805 	    printsub('>', &str_lm[2], sizeof(str_lm)-2);
806 	}
807 /*@*/	else printf("lm_will: not enough room in buffer\n");
808 	break;
809     }
810 }
811 
812 lm_wont(cmd, len)
813 char *cmd;
814 {
815     switch(cmd[0]) {
816     case LM_FORWARDMASK:	/* We shouldn't ever get this... */
817     default:
818 	/* We are always DONT, so don't respond */
819 	return;
820     }
821 }
822 
823 lm_do(cmd, len)
824 char *cmd;
825 {
826     switch(cmd[0]) {
827     case LM_FORWARDMASK:
828     default:
829 	str_lm[3] = WONT;
830 	str_lm[4] = cmd[0];
831 	if (NETROOM() > sizeof(str_lm)) {
832 	    ring_supply_data(&netoring, str_lm, sizeof(str_lm));
833 	    printsub('>', &str_lm[2], sizeof(str_lm)-2);
834 	}
835 /*@*/	else printf("lm_do: not enough room in buffer\n");
836 	break;
837     }
838 }
839 
840 lm_dont(cmd, len)
841 char *cmd;
842 {
843     switch(cmd[0]) {
844     case LM_FORWARDMASK:
845     default:
846 	/* we are always WONT, so don't respond */
847 	break;
848     }
849 }
850 
851 static char str_lm_mode[] = { IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE };
852 
853 lm_mode(cmd, len, init)
854 char *cmd;
855 int len, init;
856 {
857 	if (len != 1)
858 		return;
859 	if ((linemode&(MODE_EDIT|MODE_TRAPSIG)) == *cmd)
860 		return;
861 	if (*cmd&MODE_ACK)
862 		return;
863 	linemode = (*cmd&(MODE_EDIT|MODE_TRAPSIG));
864 	str_lm_mode[4] = linemode;
865 	if (!init)
866 	    str_lm_mode[4] |= MODE_ACK;
867 	if (NETROOM() > sizeof(str_lm_mode)) {
868 	    ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
869 	    printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
870 	}
871 /*@*/	else printf("lm_mode: not enough room in buffer\n");
872 	setconnmode(0);	/* set changed mode */
873 }
874 
875 
876 
877 /*
878  * slc()
879  * Handle special character suboption of LINEMODE.
880  */
881 
882 struct spc {
883 	cc_t val;
884 	cc_t *valp;
885 	char flags;	/* Current flags & level */
886 	char mylevel;	/* Maximum level & flags */
887 } spc_data[NSLC+1];
888 
889 #define SLC_IMPORT	0
890 #define	SLC_EXPORT	1
891 #define SLC_RVALUE	2
892 static int slc_mode = SLC_EXPORT;
893 
894 slc_init()
895 {
896 	register struct spc *spcp;
897 	extern cc_t *tcval();
898 
899 	localchars = 1;
900 	for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
901 		spcp->val = 0;
902 		spcp->valp = 0;
903 		spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
904 	}
905 
906 #define	initfunc(func, flags) { \
907 					spcp = &spc_data[func]; \
908 					if (spcp->valp = tcval(func)) { \
909 					    spcp->val = *spcp->valp; \
910 					    spcp->mylevel = SLC_VARIABLE|flags; \
911 					} else { \
912 					    spcp->val = 0; \
913 					    spcp->mylevel = SLC_DEFAULT; \
914 					} \
915 				    }
916 
917 	initfunc(SLC_SYNCH, 0);
918 	/* No BRK */
919 	initfunc(SLC_AO, 0);
920 	initfunc(SLC_AYT, 0);
921 	/* No EOR */
922 	initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
923 	initfunc(SLC_EOF, 0);
924 #ifndef	SYSV_TERMIO
925 	initfunc(SLC_SUSP, SLC_FLUSHIN);
926 #endif
927 	initfunc(SLC_EC, 0);
928 	initfunc(SLC_EL, 0);
929 #ifndef	SYSV_TERMIO
930 	initfunc(SLC_EW, 0);
931 	initfunc(SLC_RP, 0);
932 	initfunc(SLC_LNEXT, 0);
933 #endif
934 	initfunc(SLC_XON, 0);
935 	initfunc(SLC_XOFF, 0);
936 #ifdef	SYSV_TERMIO
937 	spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
938 	spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
939 #endif
940 	/* No FORW1 */
941 	/* No FORW2 */
942 
943 	initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
944 #undef	initfunc
945 
946 	if (slc_mode == SLC_EXPORT)
947 		slc_export();
948 	else
949 		slc_import(1);
950 
951 }
952 
953 slcstate()
954 {
955     printf("Special characters are %s values\n",
956 		slc_mode == SLC_IMPORT ? "remote default" :
957 		slc_mode == SLC_EXPORT ? "local" :
958 					 "remote");
959 }
960 
961 slc_mode_export()
962 {
963     slc_mode = SLC_EXPORT;
964     if (my_state_is_will(TELOPT_LINEMODE))
965 	slc_export();
966 }
967 
968 slc_mode_import(def)
969 {
970     slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
971     if (my_state_is_will(TELOPT_LINEMODE))
972 	slc_import(def);
973 }
974 
975 char slc_import_val[] = {
976 	IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
977 };
978 char slc_import_def[] = {
979 	IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
980 };
981 
982 slc_import(def)
983 int def;
984 {
985     if (NETROOM() > sizeof(slc_import_val)) {
986 	if (def) {
987 	    ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
988 	    printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
989 	} else {
990 	    ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
991 	    printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
992 	}
993     }
994 /*@*/ else printf("slc_import: not enough room\n");
995 }
996 
997 slc_export()
998 {
999     register struct spc *spcp;
1000 
1001     TerminalDefaultChars();
1002 
1003     slc_start_reply();
1004     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1005 	if (spcp->mylevel != SLC_NOSUPPORT) {
1006 	    spcp->flags = spcp->mylevel;
1007 	    if (spcp->valp)
1008 		spcp->val = *spcp->valp;
1009 	    slc_add_reply(spcp - spc_data, spcp->mylevel, spcp->val);
1010 	}
1011     }
1012     slc_end_reply();
1013     if (slc_update())
1014 	setconnmode(1);	/* set the  new character values */
1015 }
1016 
1017 slc(cp, len)
1018 register char *cp;
1019 int len;
1020 {
1021 	register struct spc *spcp;
1022 	register int func,level;
1023 
1024 	slc_start_reply();
1025 
1026 	for (; len >= 3; len -=3, cp +=3) {
1027 
1028 		func = cp[SLC_FUNC];
1029 
1030 		if (func == 0) {
1031 			/*
1032 			 * Client side: always ignore 0 function.
1033 			 */
1034 			continue;
1035 		}
1036 		if (func > NSLC) {
1037 			if (cp[SLC_FLAGS] & SLC_LEVELBITS != SLC_NOSUPPORT)
1038 				slc_add_reply(func, SLC_NOSUPPORT, 0);
1039 			continue;
1040 		}
1041 
1042 		spcp = &spc_data[func];
1043 
1044 		level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
1045 
1046 		if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
1047 		    ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
1048 			continue;
1049 		}
1050 
1051 		if (level == (SLC_DEFAULT|SLC_ACK)) {
1052 			/*
1053 			 * This is an error condition, the SLC_ACK
1054 			 * bit should never be set for the SLC_DEFAULT
1055 			 * level.  Our best guess to recover is to
1056 			 * ignore the SLC_ACK bit.
1057 			 */
1058 			cp[SLC_FLAGS] &= ~SLC_ACK;
1059 		}
1060 
1061 		if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
1062 			spcp->val = (cc_t)cp[SLC_VALUE];
1063 			spcp->flags = cp[SLC_FLAGS];	/* include SLC_ACK */
1064 			continue;
1065 		}
1066 
1067 		level &= ~SLC_ACK;
1068 
1069 		if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
1070 			spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
1071 			spcp->val = (cc_t)cp[SLC_VALUE];
1072 		}
1073 		if (level == SLC_DEFAULT) {
1074 			if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
1075 				spcp->flags = spcp->mylevel;
1076 			else
1077 				spcp->flags = SLC_NOSUPPORT;
1078 		}
1079 		slc_add_reply(func, spcp->flags, spcp->val);
1080 	}
1081 	slc_end_reply();
1082 	if (slc_update())
1083 		setconnmode(1);	/* set the  new character values */
1084 }
1085 
1086 slc_check()
1087 {
1088     register struct spc *spcp;
1089 
1090     slc_start_reply();
1091     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1092 	if (spcp->valp && spcp->val != *spcp->valp) {
1093 	    spcp->val = *spcp->valp;
1094 	    slc_add_reply(spcp - spc_data, spcp->mylevel, spcp->val);
1095 	}
1096     }
1097     slc_end_reply();
1098     setconnmode(1);
1099 }
1100 
1101 
1102 unsigned char slc_reply[128];
1103 unsigned char *slc_replyp;
1104 slc_start_reply()
1105 {
1106 	slc_replyp = slc_reply;
1107 	*slc_replyp++ = IAC;
1108 	*slc_replyp++ = SB;
1109 	*slc_replyp++ = TELOPT_LINEMODE;
1110 	*slc_replyp++ = LM_SLC;
1111 }
1112 
1113 slc_add_reply(func, flags, value)
1114 char func;
1115 char flags;
1116 cc_t value;
1117 {
1118 	if ((*slc_replyp++ = func) == IAC)
1119 		*slc_replyp++ = IAC;
1120 	if ((*slc_replyp++ = flags) == IAC)
1121 		*slc_replyp++ = IAC;
1122 	if ((*slc_replyp++ = (unsigned char)value) == IAC)
1123 		*slc_replyp++ = IAC;
1124 }
1125 
1126 slc_end_reply()
1127 {
1128     register char *cp;
1129     register int len;
1130 
1131     *slc_replyp++ = IAC;
1132     *slc_replyp++ = SE;
1133     len = slc_replyp - slc_reply;
1134     if (len <= 6)
1135 	return;
1136     if (NETROOM() > len) {
1137 	ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1138 	printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1139     }
1140 /*@*/else printf("slc_end_reply: not enough room\n");
1141 }
1142 
1143 slc_update()
1144 {
1145 	register struct spc *spcp;
1146 	int need_update = 0;
1147 
1148 	for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1149 		if (!(spcp->flags&SLC_ACK))
1150 			continue;
1151 		spcp->flags &= ~SLC_ACK;
1152 		if (spcp->valp && (*spcp->valp != spcp->val)) {
1153 			*spcp->valp = spcp->val;
1154 			need_update = 1;
1155 		}
1156 	}
1157 	return(need_update);
1158 }
1159 
1160 
1161 
1162 int
1163 telrcv()
1164 {
1165     register int c;
1166     register int scc;
1167     register char *sbp;
1168     int count;
1169     int returnValue = 0;
1170 
1171     scc = 0;
1172     count = 0;
1173     while (TTYROOM() > 2) {
1174 	if (scc == 0) {
1175 	    if (count) {
1176 		ring_consumed(&netiring, count);
1177 		returnValue = 1;
1178 		count = 0;
1179 	    }
1180 	    sbp = netiring.consume;
1181 	    scc = ring_full_consecutive(&netiring);
1182 	    if (scc == 0) {
1183 		/* No more data coming in */
1184 		break;
1185 	    }
1186 	}
1187 
1188 	c = *sbp++ & 0xff, scc--; count++;
1189 
1190 	switch (telrcv_state) {
1191 
1192 	case TS_CR:
1193 	    telrcv_state = TS_DATA;
1194 	    if (c == '\0') {
1195 		break;	/* Ignore \0 after CR */
1196 	    }
1197 	    else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1198 		TTYADD(c);
1199 		break;
1200 	    }
1201 	    /* Else, fall through */
1202 
1203 	case TS_DATA:
1204 	    if (c == IAC) {
1205 		telrcv_state = TS_IAC;
1206 		break;
1207 	    }
1208 #	    if defined(TN3270)
1209 	    if (In3270) {
1210 		*Ifrontp++ = c;
1211 		while (scc > 0) {
1212 		    c = *sbp++ & 0377, scc--; count++;
1213 		    if (c == IAC) {
1214 			telrcv_state = TS_IAC;
1215 			break;
1216 		    }
1217 		    *Ifrontp++ = c;
1218 		}
1219 	    } else
1220 #	    endif /* defined(TN3270) */
1221 		    /*
1222 		     * The 'crmod' hack (see following) is needed
1223 		     * since we can't * set CRMOD on output only.
1224 		     * Machines like MULTICS like to send \r without
1225 		     * \n; since we must turn off CRMOD to get proper
1226 		     * input, the mapping is done here (sigh).
1227 		     */
1228 	    if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
1229 		if (scc > 0) {
1230 		    c = *sbp&0xff;
1231 		    if (c == 0) {
1232 			sbp++, scc--; count++;
1233 			/* a "true" CR */
1234 			TTYADD('\r');
1235 		    } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1236 					(c == '\n')) {
1237 			sbp++, scc--; count++;
1238 			TTYADD('\n');
1239 		    } else {
1240 			TTYADD('\r');
1241 			if (crmod) {
1242 				TTYADD('\n');
1243 			}
1244 		    }
1245 		} else {
1246 		    telrcv_state = TS_CR;
1247 		    TTYADD('\r');
1248 		    if (crmod) {
1249 			    TTYADD('\n');
1250 		    }
1251 		}
1252 	    } else {
1253 		TTYADD(c);
1254 	    }
1255 	    continue;
1256 
1257 	case TS_IAC:
1258 process_iac:
1259 	    switch (c) {
1260 
1261 	    case WILL:
1262 		telrcv_state = TS_WILL;
1263 		continue;
1264 
1265 	    case WONT:
1266 		telrcv_state = TS_WONT;
1267 		continue;
1268 
1269 	    case DO:
1270 		telrcv_state = TS_DO;
1271 		continue;
1272 
1273 	    case DONT:
1274 		telrcv_state = TS_DONT;
1275 		continue;
1276 
1277 	    case DM:
1278 		    /*
1279 		     * We may have missed an urgent notification,
1280 		     * so make sure we flush whatever is in the
1281 		     * buffer currently.
1282 		     */
1283 		SYNCHing = 1;
1284 		ttyflush(1);
1285 		SYNCHing = stilloob();
1286 		settimer(gotDM);
1287 		break;
1288 
1289 	    case NOP:
1290 	    case GA:
1291 		break;
1292 
1293 	    case SB:
1294 		SB_CLEAR();
1295 		telrcv_state = TS_SB;
1296 		printoption("RCVD", "IAC", SB);
1297 		continue;
1298 
1299 #	    if defined(TN3270)
1300 	    case EOR:
1301 		if (In3270) {
1302 		    Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
1303 		    if (Ibackp == Ifrontp) {
1304 			Ibackp = Ifrontp = Ibuf;
1305 			ISend = 0;	/* should have been! */
1306 		    } else {
1307 			ISend = 1;
1308 		    }
1309 		}
1310 		break;
1311 #	    endif /* defined(TN3270) */
1312 
1313 	    case IAC:
1314 #	    if !defined(TN3270)
1315 		TTYADD(IAC);
1316 #	    else /* !defined(TN3270) */
1317 		if (In3270) {
1318 		    *Ifrontp++ = IAC;
1319 		} else {
1320 		    TTYADD(IAC);
1321 		}
1322 #	    endif /* !defined(TN3270) */
1323 		break;
1324 
1325 	    default:
1326 		break;
1327 	    }
1328 	    telrcv_state = TS_DATA;
1329 	    continue;
1330 
1331 	case TS_WILL:
1332 	    printoption("RCVD", "will", c);
1333 	    willoption(c);
1334 	    SetIn3270();
1335 	    telrcv_state = TS_DATA;
1336 	    continue;
1337 
1338 	case TS_WONT:
1339 	    printoption("RCVD", "wont", c);
1340 	    wontoption(c);
1341 	    SetIn3270();
1342 	    telrcv_state = TS_DATA;
1343 	    continue;
1344 
1345 	case TS_DO:
1346 	    printoption("RCVD", "do", c);
1347 	    dooption(c);
1348 	    SetIn3270();
1349 	    if (c == TELOPT_NAWS) {
1350 		sendnaws();
1351 	    } else if (c == TELOPT_LFLOW) {
1352 		localflow = 1;
1353 		setcommandmode();
1354 		setconnmode(0);
1355 	    }
1356 	    telrcv_state = TS_DATA;
1357 	    continue;
1358 
1359 	case TS_DONT:
1360 	    printoption("RCVD", "dont", c);
1361 	    dontoption(c);
1362 	    flushline = 1;
1363 	    setconnmode(0);	/* set new tty mode (maybe) */
1364 	    SetIn3270();
1365 	    telrcv_state = TS_DATA;
1366 	    continue;
1367 
1368 	case TS_SB:
1369 	    if (c == IAC) {
1370 		telrcv_state = TS_SE;
1371 	    } else {
1372 		SB_ACCUM(c);
1373 	    }
1374 	    continue;
1375 
1376 	case TS_SE:
1377 	    if (c != SE) {
1378 		if (c != IAC) {
1379 		    /*
1380 		     * This is an error.  We only expect to get
1381 		     * "IAC IAC" or "IAC SE".  Several things may
1382 		     * have happend.  An IAC was not doubled, the
1383 		     * IAC SE was left off, or another option got
1384 		     * inserted into the suboption are all possibilities.
1385 		     * If we assume that the IAC was not doubled,
1386 		     * and really the IAC SE was left off, we could
1387 		     * get into an infinate loop here.  So, instead,
1388 		     * we terminate the suboption, and process the
1389 		     * partial suboption if we can.
1390 		     */
1391 		    SB_TERM();
1392 		    SB_ACCUM(IAC);
1393 		    SB_ACCUM(c);
1394 		    printoption("In SUBOPTION processing, RCVD", "IAC", c);
1395 		    suboption();	/* handle sub-option */
1396 		    SetIn3270();
1397 		    telrcv_state = TS_IAC;
1398 		    goto process_iac;
1399 		}
1400 		SB_ACCUM(c);
1401 		telrcv_state = TS_SB;
1402 	    } else {
1403 		SB_TERM();
1404 		SB_ACCUM(IAC);
1405 		SB_ACCUM(SE);
1406 		suboption();	/* handle sub-option */
1407 		SetIn3270();
1408 		telrcv_state = TS_DATA;
1409 	    }
1410 	}
1411     }
1412     if (count)
1413 	ring_consumed(&netiring, count);
1414     return returnValue||count;
1415 }
1416 
1417 static int
1418 telsnd()
1419 {
1420     int tcc;
1421     int count;
1422     int returnValue = 0;
1423     char *tbp;
1424 
1425     tcc = 0;
1426     count = 0;
1427     while (NETROOM() > 2) {
1428 	register int sc;
1429 	register int c;
1430 
1431 	if (tcc == 0) {
1432 	    if (count) {
1433 		ring_consumed(&ttyiring, count);
1434 		returnValue = 1;
1435 		count = 0;
1436 	    }
1437 	    tbp = ttyiring.consume;
1438 	    tcc = ring_full_consecutive(&ttyiring);
1439 	    if (tcc == 0) {
1440 		break;
1441 	    }
1442 	}
1443 	c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
1444 	if (sc == escape) {
1445 	    /*
1446 	     * Double escape is a pass through of a single escape character.
1447 	     */
1448 	    if (tcc && strip(*tbp) == escape) {
1449 		tbp++;
1450 		tcc--;
1451 		count++;
1452 	    } else {
1453 		command(0, tbp, tcc);
1454 		count += tcc;
1455 		tcc = 0;
1456 		flushline = 1;
1457 		break;
1458 	    }
1459 	}
1460 #ifdef	KLUDGELINEMODE
1461 	if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
1462 	    if (tcc > 0 && strip(*tbp) == echoc) {
1463 		tcc--; tbp++; count++;
1464 	    } else {
1465 		dontlecho = !dontlecho;
1466 		settimer(echotoggle);
1467 		setconnmode(0);
1468 		flushline = 1;
1469 		break;
1470 	    }
1471 	}
1472 #endif
1473 	if (MODE_LOCAL_CHARS(globalmode)) {
1474 	    if (TerminalSpecialChars(sc) == 0) {
1475 		break;
1476 	    }
1477 	}
1478 	if (my_want_state_is_wont(TELOPT_BINARY)) {
1479 	    switch (c) {
1480 	    case '\n':
1481 		    /*
1482 		     * If we are in CRMOD mode (\r ==> \n)
1483 		     * on our local machine, then probably
1484 		     * a newline (unix) is CRLF (TELNET).
1485 		     */
1486 		if (MODE_LOCAL_CHARS(globalmode)) {
1487 		    NETADD('\r');
1488 		}
1489 		NETADD('\n');
1490 		flushline = 1;
1491 		break;
1492 	    case '\r':
1493 		if (!crlf) {
1494 		    NET2ADD('\r', '\0');
1495 		} else {
1496 		    NET2ADD('\r', '\n');
1497 		}
1498 		flushline = 1;
1499 		break;
1500 	    case IAC:
1501 		NET2ADD(IAC, IAC);
1502 		break;
1503 	    default:
1504 		NETADD(c);
1505 		break;
1506 	    }
1507 	} else if (c == IAC) {
1508 	    NET2ADD(IAC, IAC);
1509 	} else {
1510 	    NETADD(c);
1511 	}
1512     }
1513     if (count)
1514 	ring_consumed(&ttyiring, count);
1515     return returnValue||count;		/* Non-zero if we did anything */
1516 }
1517 
1518 /*
1519  * Scheduler()
1520  *
1521  * Try to do something.
1522  *
1523  * If we do something useful, return 1; else return 0.
1524  *
1525  */
1526 
1527 
1528 int
1529 Scheduler(block)
1530 int	block;			/* should we block in the select ? */
1531 {
1532 		/* One wants to be a bit careful about setting returnValue
1533 		 * to one, since a one implies we did some useful work,
1534 		 * and therefore probably won't be called to block next
1535 		 * time (TN3270 mode only).
1536 		 */
1537     int returnValue;
1538     int netin, netout, netex, ttyin, ttyout;
1539 
1540     /* Decide which rings should be processed */
1541 
1542     netout = ring_full_count(&netoring) &&
1543 	    (flushline ||
1544 		(my_want_state_is_wont(TELOPT_LINEMODE)
1545 #ifdef	KLUDGELINEMODE
1546 			&& (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
1547 #endif
1548 		) ||
1549 			my_want_state_is_will(TELOPT_BINARY));
1550     ttyout = ring_full_count(&ttyoring);
1551 
1552 #if	defined(TN3270)
1553     ttyin = ring_empty_count(&ttyiring) && (shell_active == 0);
1554 #else	/* defined(TN3270) */
1555     ttyin = ring_empty_count(&ttyiring);
1556 #endif	/* defined(TN3270) */
1557 
1558 #if	defined(TN3270)
1559     netin = ring_empty_count(&netiring);
1560 #   else /* !defined(TN3270) */
1561     netin = !ISend && ring_empty_count(&netiring);
1562 #   endif /* !defined(TN3270) */
1563 
1564     netex = !SYNCHing;
1565 
1566     /* If we have seen a signal recently, reset things */
1567 #   if defined(TN3270) && defined(unix)
1568     if (HaveInput) {
1569 	HaveInput = 0;
1570 	signal(SIGIO, inputAvailable);
1571     }
1572 #endif	/* defined(TN3270) && defined(unix) */
1573 
1574     /* Call to system code to process rings */
1575 
1576     returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
1577 
1578     /* Now, look at the input rings, looking for work to do. */
1579 
1580     if (ring_full_count(&ttyiring)) {
1581 #   if defined(TN3270)
1582 	if (In3270) {
1583 	    int c;
1584 
1585 	    c = DataFromTerminal(ttyiring.consume,
1586 					ring_full_consecutive(&ttyiring));
1587 	    if (c) {
1588 		returnValue = 1;
1589 	        ring_consumed(&ttyiring, c);
1590 	    }
1591 	} else {
1592 #   endif /* defined(TN3270) */
1593 	    returnValue |= telsnd();
1594 #   if defined(TN3270)
1595 	}
1596 #   endif /* defined(TN3270) */
1597     }
1598 
1599     if (ring_full_count(&netiring)) {
1600 #	if !defined(TN3270)
1601 	returnValue |= telrcv();
1602 #	else /* !defined(TN3270) */
1603 	returnValue = Push3270();
1604 #	endif /* !defined(TN3270) */
1605     }
1606     return returnValue;
1607 }
1608 
1609 /*
1610  * Select from tty and network...
1611  */
1612 void
1613 telnet()
1614 {
1615     sys_telnet_init();
1616 
1617 #   if !defined(TN3270)
1618     if (telnetport) {
1619 	send_do(TELOPT_SGA, 1);
1620 	send_will(TELOPT_TTYPE, 1);
1621 	send_will(TELOPT_NAWS, 1);
1622 	send_will(TELOPT_TSPEED, 1);
1623 	send_will(TELOPT_LFLOW, 1);
1624 	send_will(TELOPT_LINEMODE, 1);
1625 	send_do(TELOPT_STATUS, 1);
1626     }
1627 #   endif /* !defined(TN3270) */
1628 
1629 #   if !defined(TN3270)
1630     for (;;) {
1631 	int schedValue;
1632 
1633 	while ((schedValue = Scheduler(0)) != 0) {
1634 	    if (schedValue == -1) {
1635 		setcommandmode();
1636 		return;
1637 	    }
1638 	}
1639 
1640 	if (Scheduler(1) == -1) {
1641 	    setcommandmode();
1642 	    return;
1643 	}
1644     }
1645 #   else /* !defined(TN3270) */
1646     for (;;) {
1647 	int schedValue;
1648 
1649 	while (!In3270 && !shell_active) {
1650 	    if (Scheduler(1) == -1) {
1651 		setcommandmode();
1652 		return;
1653 	    }
1654 	}
1655 
1656 	while ((schedValue = Scheduler(0)) != 0) {
1657 	    if (schedValue == -1) {
1658 		setcommandmode();
1659 		return;
1660 	    }
1661 	}
1662 		/* If there is data waiting to go out to terminal, don't
1663 		 * schedule any more data for the terminal.
1664 		 */
1665 	if (ring_full_count(&ttyoring)) {
1666 	    schedValue = 1;
1667 	} else {
1668 	    if (shell_active) {
1669 		if (shell_continue() == 0) {
1670 		    ConnectScreen();
1671 		}
1672 	    } else if (In3270) {
1673 		schedValue = DoTerminalOutput();
1674 	    }
1675 	}
1676 	if (schedValue && (shell_active == 0)) {
1677 	    if (Scheduler(1) == -1) {
1678 		setcommandmode();
1679 		return;
1680 	    }
1681 	}
1682     }
1683 #   endif /* !defined(TN3270) */
1684 }
1685 
1686 #if	0	/* XXX - this not being in is a bug */
1687 /*
1688  * nextitem()
1689  *
1690  *	Return the address of the next "item" in the TELNET data
1691  * stream.  This will be the address of the next character if
1692  * the current address is a user data character, or it will
1693  * be the address of the character following the TELNET command
1694  * if the current address is a TELNET IAC ("I Am a Command")
1695  * character.
1696  */
1697 
1698 static char *
1699 nextitem(current)
1700 char	*current;
1701 {
1702     if ((*current&0xff) != IAC) {
1703 	return current+1;
1704     }
1705     switch (*(current+1)&0xff) {
1706     case DO:
1707     case DONT:
1708     case WILL:
1709     case WONT:
1710 	return current+3;
1711     case SB:		/* loop forever looking for the SE */
1712 	{
1713 	    register char *look = current+2;
1714 
1715 	    for (;;) {
1716 		if ((*look++&0xff) == IAC) {
1717 		    if ((*look++&0xff) == SE) {
1718 			return look;
1719 		    }
1720 		}
1721 	    }
1722 	}
1723     default:
1724 	return current+2;
1725     }
1726 }
1727 #endif	/* 0 */
1728 
1729 /*
1730  * netclear()
1731  *
1732  *	We are about to do a TELNET SYNCH operation.  Clear
1733  * the path to the network.
1734  *
1735  *	Things are a bit tricky since we may have sent the first
1736  * byte or so of a previous TELNET command into the network.
1737  * So, we have to scan the network buffer from the beginning
1738  * until we are up to where we want to be.
1739  *
1740  *	A side effect of what we do, just to keep things
1741  * simple, is to clear the urgent data pointer.  The principal
1742  * caller should be setting the urgent data pointer AFTER calling
1743  * us in any case.
1744  */
1745 
1746 static void
1747 netclear()
1748 {
1749 #if	0	/* XXX */
1750     register char *thisitem, *next;
1751     char *good;
1752 #define	wewant(p)	((nfrontp > p) && ((*p&0xff) == IAC) && \
1753 				((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
1754 
1755     thisitem = netobuf;
1756 
1757     while ((next = nextitem(thisitem)) <= netobuf.send) {
1758 	thisitem = next;
1759     }
1760 
1761     /* Now, thisitem is first before/at boundary. */
1762 
1763     good = netobuf;	/* where the good bytes go */
1764 
1765     while (netoring.add > thisitem) {
1766 	if (wewant(thisitem)) {
1767 	    int length;
1768 
1769 	    next = thisitem;
1770 	    do {
1771 		next = nextitem(next);
1772 	    } while (wewant(next) && (nfrontp > next));
1773 	    length = next-thisitem;
1774 	    memcpy(good, thisitem, length);
1775 	    good += length;
1776 	    thisitem = next;
1777 	} else {
1778 	    thisitem = nextitem(thisitem);
1779 	}
1780     }
1781 
1782 #endif	/* 0 */
1783 }
1784 
1785 /*
1786  * These routines add various telnet commands to the data stream.
1787  */
1788 
1789 static void
1790 doflush()
1791 {
1792     NET2ADD(IAC, DO);
1793     NETADD(TELOPT_TM);
1794     flushline = 1;
1795     flushout = 1;
1796     ttyflush(1);			/* Flush/drop output */
1797     /* do printoption AFTER flush, otherwise the output gets tossed... */
1798     printoption("SENT", "do", TELOPT_TM);
1799 }
1800 
1801 void
1802 xmitAO()
1803 {
1804     NET2ADD(IAC, AO);
1805     printoption("SENT", "IAC", AO);
1806     if (autoflush) {
1807 	doflush();
1808     }
1809 }
1810 
1811 
1812 void
1813 xmitEL()
1814 {
1815     NET2ADD(IAC, EL);
1816     printoption("SENT", "IAC", EL);
1817 }
1818 
1819 void
1820 xmitEC()
1821 {
1822     NET2ADD(IAC, EC);
1823     printoption("SENT", "IAC", EC);
1824 }
1825 
1826 
1827 #if	defined(NOT43)
1828 int
1829 #else	/* defined(NOT43) */
1830 void
1831 #endif	/* defined(NOT43) */
1832 dosynch()
1833 {
1834     netclear();			/* clear the path to the network */
1835     NETADD(IAC);
1836     setneturg();
1837     NETADD(DM);
1838     printoption("SENT", "IAC", DM);
1839 
1840 #if	defined(NOT43)
1841     return 0;
1842 #endif	/* defined(NOT43) */
1843 }
1844 
1845 void
1846 get_status()
1847 {
1848     char tmp[16];
1849     register char *cp;
1850 
1851     if (my_want_state_is_dont(TELOPT_STATUS)) {
1852 	printf("Remote side does not support STATUS option\n");
1853 	return;
1854     }
1855     if (!showoptions)
1856 	printf("You will not see the response unless you set \"options\"\n");
1857 
1858     cp = tmp;
1859 
1860     *cp++ = IAC;
1861     *cp++ = SB;
1862     *cp++ = TELOPT_STATUS;
1863     *cp++ = TELQUAL_SEND;
1864     *cp++ = IAC;
1865     *cp++ = SE;
1866     if (NETROOM() >= cp - tmp) {
1867 	ring_supply_data(&netoring, tmp, cp-tmp);
1868 	printsub('>', tmp+2, cp - tmp - 2);
1869     }
1870 }
1871 
1872 void
1873 intp()
1874 {
1875     NET2ADD(IAC, IP);
1876     printoption("SENT", "IAC", IP);
1877     flushline = 1;
1878     if (autoflush) {
1879 	doflush();
1880     }
1881     if (autosynch) {
1882 	dosynch();
1883     }
1884 }
1885 
1886 void
1887 sendbrk()
1888 {
1889     NET2ADD(IAC, BREAK);
1890     printoption("SENT", "IAC", BREAK);
1891     flushline = 1;
1892     if (autoflush) {
1893 	doflush();
1894     }
1895     if (autosynch) {
1896 	dosynch();
1897     }
1898 }
1899 
1900 void
1901 sendabort()
1902 {
1903     NET2ADD(IAC, ABORT);
1904     printoption("SENT", "IAC", ABORT);
1905     flushline = 1;
1906     if (autoflush) {
1907 	doflush();
1908     }
1909     if (autosynch) {
1910 	dosynch();
1911     }
1912 }
1913 
1914 void
1915 sendsusp()
1916 {
1917     NET2ADD(IAC, SUSP);
1918     printoption("SENT", "IAC", SUSP);
1919     flushline = 1;
1920     if (autoflush) {
1921 	doflush();
1922     }
1923     if (autosynch) {
1924 	dosynch();
1925     }
1926 }
1927 
1928 void
1929 sendeof()
1930 {
1931     NET2ADD(IAC, xEOF);
1932     printoption("SENT", "IAC", xEOF);
1933 }
1934 
1935 /*
1936  * Send a window size update to the remote system.
1937  */
1938 
1939 void
1940 sendnaws()
1941 {
1942     long rows, cols;
1943     unsigned char tmp[16];
1944     register unsigned char *cp;
1945 
1946     if (my_state_is_wont(TELOPT_NAWS))
1947 	return;
1948 
1949 #define	PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
1950 			    if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
1951 
1952     if (TerminalWindowSize(&rows, &cols) == 0) {	/* Failed */
1953 	return;
1954     }
1955 
1956     cp = tmp;
1957 
1958     *cp++ = IAC;
1959     *cp++ = SB;
1960     *cp++ = TELOPT_NAWS;
1961     PUTSHORT(cp, cols);
1962     PUTSHORT(cp, rows);
1963     *cp++ = IAC;
1964     *cp++ = SE;
1965     if (NETROOM() >= cp - tmp) {
1966 	ring_supply_data(&netoring, tmp, cp-tmp);
1967 	printsub('>', tmp+2, cp - tmp - 2);
1968     }
1969 }
1970 
1971 tel_enter_binary(rw)
1972 int rw;
1973 {
1974     if (rw&1)
1975 	send_do(TELOPT_BINARY, 1);
1976     if (rw&2)
1977 	send_will(TELOPT_BINARY, 1);
1978 }
1979 
1980 tel_leave_binary(rw)
1981 int rw;
1982 {
1983     if (rw&1)
1984 	send_dont(TELOPT_BINARY, 1);
1985     if (rw&2)
1986 	send_wont(TELOPT_BINARY, 1);
1987 }
1988