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