1 /*
2  * Copyright 1994-2002 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * usr/src/cmd/cmd-inet/usr.bin/telnet/terminal.c
10  */
11 
12 /*
13  * Copyright (c) 1988, 1990, 1993
14  *	The Regents of the University of California.  All rights reserved.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. All advertising materials mentioning features or use of this software
25  *    must display the following acknowledgement:
26  *	This product includes software developed by the University of
27  *	California, Berkeley and its contributors.
28  * 4. Neither the name of the University nor the names of its contributors
29  *    may be used to endorse or promote products derived from this software
30  *    without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42  * SUCH DAMAGE.
43  */
44 
45 #ifndef lint
46 static char sccsid[] = "@(#)terminal.c	8.1 (Berkeley) 6/6/93";
47 #endif /* not lint */
48 
49 #include <arpa/telnet.h>
50 #include <sys/types.h>
51 #include <errno.h>
52 
53 #include "ring.h"
54 
55 #include "externs.h"
56 #include "types.h"
57 
58 Ring	ttyoring;
59 Ring	ttyiring;
60 static unsigned char ttyobuf[2*BUFSIZ];
61 static unsigned char ttyibuf[BUFSIZ];
62 
63 int termdata;			/* Debugging flag */
64 
65 #ifdef	USE_TERMIO
66 cc_t termAytChar;
67 #else
68 cc_t termForw2Char;
69 cc_t termAytChar;
70 #endif
71 
72 /*
73  * initialize the terminal data structures.
74  */
75 
76     void
init_terminal()77 init_terminal()
78 {
79 	if (ring_init(&ttyoring, ttyobuf, sizeof (ttyobuf)) != 1) {
80 		exit(1);
81 	}
82 	if (ring_init(&ttyiring, ttyibuf, sizeof (ttyibuf)) != 1) {
83 		exit(1);
84 	}
85 	autoflush = 1;
86 }
87 
88 
89 /*
90  *		Send as much data as possible to the terminal.
91  *
92  *		Return value:
93  *			-2: Error occurred other than EWOULDBLOCK; see
94  *			    'errno' for specifics
95  *			-1: No useful work done, although data was waiting.
96  *			    This may be due to EWOULDBLOCK error.
97  *			 0: No data was waiting, so nothing was done.
98  *			 1: All waiting data was written out.
99  *			 n: Part of data was written.  'n' is the number
100  *			    of bytes remaining which were not written.
101  */
102 
103 int
ttyflush(drop)104 ttyflush(drop)
105 	int drop;
106 {
107 	register int n, n0, n1;
108 
109 	n0 = ring_full_count(&ttyoring);
110 	if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) {
111 		if (drop) {
112 			TerminalFlushOutput();
113 			/* we leave 'n' alone! */
114 		} else {
115 			n = TerminalWrite((char *)ttyoring.consume, n);
116 			if (n == -1 && errno != EWOULDBLOCK)
117 				return (-2);
118 		}
119 	}
120 	if (n > 0) {
121 		if (termdata && n) {
122 			Dump('>', ttyoring.consume, n);
123 		}
124 		/*
125 		 * If we wrote everything, and the full count is
126 		 * larger than what we wrote, then write the
127 		 * rest of the buffer.
128 		 */
129 		if (n1 == n && n0 > n) {
130 			n1 = n0 - n;
131 			if (!drop) {
132 				n1 = TerminalWrite((char *)ttyoring.bottom, n1);
133 				if (n1 == -1) {
134 					if (errno != EWOULDBLOCK)
135 						return (-2);
136 					n1 = 0;
137 				}
138 			}
139 			n += n1;
140 		}
141 		ring_consumed(&ttyoring, n);
142 	}
143 	if (n < 0)
144 		return (-1);
145 
146 	if (n == n0) {
147 		if (n0)
148 			return (-1);
149 		return (0);
150 	}
151 	return (n0 - n + 1);
152 }
153 
154 
155 /*
156  * These routines decides on what the mode should be (based on the values
157  * of various global variables).
158  */
159 
160 
161 int
getconnmode()162 getconnmode()
163 {
164 	extern int linemode;
165 	int mode = 0;
166 #ifdef	KLUDGELINEMODE
167 	extern int kludgelinemode;
168 #endif
169 
170 	if (my_want_state_is_dont(TELOPT_ECHO))
171 		mode |= MODE_ECHO;
172 
173 	if (localflow)
174 		mode |= MODE_FLOW;
175 
176 	if (my_want_state_is_will(TELOPT_BINARY))
177 		mode |= MODE_INBIN;
178 
179 	if (my_want_state_is_do(TELOPT_BINARY))
180 		mode |= MODE_OUTBIN;
181 
182 #ifdef	KLUDGELINEMODE
183 	if (kludgelinemode) {
184 		if (my_want_state_is_dont(TELOPT_SGA)) {
185 			mode |= (MODE_TRAPSIG|MODE_EDIT);
186 			if (dontlecho &&
187 			    (clocks.echotoggle > clocks.modenegotiated)) {
188 				mode &= ~MODE_ECHO;
189 			}
190 		}
191 		return (mode);
192 	}
193 #endif
194 	if (my_want_state_is_will(TELOPT_LINEMODE))
195 		mode |= linemode;
196 	return (mode);
197 }
198 
199 void
setconnmode(force)200 setconnmode(force)
201 	int force;
202 {
203 	static int enc_passwd = 0;
204 	register int newmode;
205 
206 	newmode = getconnmode()|(force?MODE_FORCE:0);
207 
208 	TerminalNewMode(newmode);
209 
210 	if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) {
211 		if (my_want_state_is_will(TELOPT_ENCRYPT) &&
212 		    (enc_passwd == 0) && !encrypt_output) {
213 			encrypt_request_start(0, 0);
214 			enc_passwd = 1;
215 		}
216 	} else {
217 		if (enc_passwd) {
218 			encrypt_request_end();
219 			enc_passwd = 0;
220 		}
221 	}
222 }
223 
224 
225     void
setcommandmode()226 setcommandmode()
227 {
228 	TerminalNewMode(-1);
229 }
230