xref: /csrg-svn/usr.bin/telnet/terminal.c (revision 32148)
1*32148Sminshall #include <arpa/telnet.h>
2*32148Sminshall 
3*32148Sminshall #include "externs.h"
4*32148Sminshall #include "types.h"
5*32148Sminshall 
6*32148Sminshall char	ttyobuf[2*BUFSIZ], *tfrontp, *tbackp;
7*32148Sminshall 
8*32148Sminshall char
9*32148Sminshall     termEofChar,
10*32148Sminshall     termEraseChar,
11*32148Sminshall     termFlushChar,
12*32148Sminshall     termIntChar,
13*32148Sminshall     termKillChar,
14*32148Sminshall     termLiteralNextChar,
15*32148Sminshall     termQuitChar;
16*32148Sminshall 
17*32148Sminshall /*
18*32148Sminshall  * initialize the terminal data structures.
19*32148Sminshall  */
20*32148Sminshall 
21*32148Sminshall init_terminal()
22*32148Sminshall {
23*32148Sminshall     tfrontp = tbackp = ttyobuf;
24*32148Sminshall     autoflush = TerminalAutoFlush();
25*32148Sminshall }
26*32148Sminshall 
27*32148Sminshall 
28*32148Sminshall /*
29*32148Sminshall  *		Send as much data as possible to the terminal.
30*32148Sminshall  *
31*32148Sminshall  *		The return value indicates whether we did any
32*32148Sminshall  *	useful work.
33*32148Sminshall  */
34*32148Sminshall 
35*32148Sminshall 
36*32148Sminshall int
37*32148Sminshall ttyflush()
38*32148Sminshall {
39*32148Sminshall     int n;
40*32148Sminshall 
41*32148Sminshall     if ((n = tfrontp - tbackp) > 0) {
42*32148Sminshall 	if (!(SYNCHing||flushout)) {
43*32148Sminshall 	    n = TerminalWrite(tout, tbackp, n);
44*32148Sminshall 	} else {
45*32148Sminshall 	    TerminalFlushOutput();
46*32148Sminshall 	    /* we leave 'n' alone! */
47*32148Sminshall 	}
48*32148Sminshall     }
49*32148Sminshall     if (n >= 0) {
50*32148Sminshall 	tbackp += n;
51*32148Sminshall 	if (tbackp == tfrontp) {
52*32148Sminshall 	    tbackp = tfrontp = ttyobuf;
53*32148Sminshall 	}
54*32148Sminshall     }
55*32148Sminshall     return n > 0;
56*32148Sminshall }
57*32148Sminshall 
58*32148Sminshall #if	defined(TN3270)
59*32148Sminshall 
60*32148Sminshall #if	defined(unix)
61*32148Sminshall static void
62*32148Sminshall inputAvailable()
63*32148Sminshall {
64*32148Sminshall     HaveInput = 1;
65*32148Sminshall }
66*32148Sminshall #endif	/* defined(unix) */
67*32148Sminshall 
68*32148Sminshall void
69*32148Sminshall outputPurge()
70*32148Sminshall {
71*32148Sminshall     int tmp = flushout;
72*32148Sminshall 
73*32148Sminshall     flushout = 1;
74*32148Sminshall 
75*32148Sminshall     ttyflush();
76*32148Sminshall 
77*32148Sminshall     flushout = tmp;
78*32148Sminshall }
79*32148Sminshall 
80*32148Sminshall #endif	/* defined(TN3270) */
81*32148Sminshall 
82*32148Sminshall #if	defined(unix)
83*32148Sminshall /*
84*32148Sminshall  * Various signal handling routines.
85*32148Sminshall  */
86*32148Sminshall 
87*32148Sminshall void
88*32148Sminshall deadpeer()
89*32148Sminshall {
90*32148Sminshall 	setcommandmode();
91*32148Sminshall 	longjmp(peerdied, -1);
92*32148Sminshall }
93*32148Sminshall 
94*32148Sminshall void
95*32148Sminshall intr()
96*32148Sminshall {
97*32148Sminshall     if (localchars) {
98*32148Sminshall 	intp();
99*32148Sminshall 	return;
100*32148Sminshall     }
101*32148Sminshall     setcommandmode();
102*32148Sminshall     longjmp(toplevel, -1);
103*32148Sminshall }
104*32148Sminshall 
105*32148Sminshall void
106*32148Sminshall intr2()
107*32148Sminshall {
108*32148Sminshall     if (localchars) {
109*32148Sminshall 	sendbrk();
110*32148Sminshall 	return;
111*32148Sminshall     }
112*32148Sminshall }
113*32148Sminshall 
114*32148Sminshall void
115*32148Sminshall doescape()
116*32148Sminshall {
117*32148Sminshall     command(0);
118*32148Sminshall }
119*32148Sminshall #endif	/* defined(unix) */
120*32148Sminshall 
121*32148Sminshall /*
122*32148Sminshall  * These routines decides on what the mode should be (based on the values
123*32148Sminshall  * of various global variables).
124*32148Sminshall  */
125*32148Sminshall 
126*32148Sminshall 
127*32148Sminshall int
128*32148Sminshall getconnmode()
129*32148Sminshall {
130*32148Sminshall     static char newmode[16] =
131*32148Sminshall 			{ 4, 5, 3, 3, 2, 2, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6 };
132*32148Sminshall     int modeindex = 0;
133*32148Sminshall 
134*32148Sminshall     if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
135*32148Sminshall 	modeindex += 1;
136*32148Sminshall     }
137*32148Sminshall     if (hisopts[TELOPT_ECHO]) {
138*32148Sminshall 	modeindex += 2;
139*32148Sminshall     }
140*32148Sminshall     if (hisopts[TELOPT_SGA]) {
141*32148Sminshall 	modeindex += 4;
142*32148Sminshall     }
143*32148Sminshall     if (In3270) {
144*32148Sminshall 	modeindex += 8;
145*32148Sminshall     }
146*32148Sminshall     return newmode[modeindex];
147*32148Sminshall }
148*32148Sminshall 
149*32148Sminshall void
150*32148Sminshall setconnmode()
151*32148Sminshall {
152*32148Sminshall     TerminalNewMode(tin, tout, getconnmode());
153*32148Sminshall }
154*32148Sminshall 
155*32148Sminshall 
156*32148Sminshall void
157*32148Sminshall setcommandmode()
158*32148Sminshall {
159*32148Sminshall     TerminalNewMode(tin, tout, 0);
160*32148Sminshall }
161*32148Sminshall 
162*32148Sminshall #if	defined(TN3270)
163*32148Sminshall 
164*32148Sminshall /*
165*32148Sminshall  * The following routines are places where the various tn3270
166*32148Sminshall  * routines make calls into telnet.c.
167*32148Sminshall  */
168*32148Sminshall 
169*32148Sminshall /* TtyChars() - returns the number of characters in the TTY buffer */
170*32148Sminshall TtyChars()
171*32148Sminshall {
172*32148Sminshall     return(tfrontp-tbackp);
173*32148Sminshall }
174*32148Sminshall 
175*32148Sminshall /*
176*32148Sminshall  * DataToNetwork - queue up some data to go to network.  If "done" is set,
177*32148Sminshall  * then when last byte is queued, we add on an IAC EOR sequence (so,
178*32148Sminshall  * don't call us with "done" until you want that done...)
179*32148Sminshall  *
180*32148Sminshall  * We actually do send all the data to the network buffer, since our
181*32148Sminshall  * only client needs for us to do that.
182*32148Sminshall  */
183*32148Sminshall 
184*32148Sminshall int
185*32148Sminshall DataToNetwork(buffer, count, done)
186*32148Sminshall register char	*buffer;	/* where the data is */
187*32148Sminshall register int	count;		/* how much to send */
188*32148Sminshall int		done;		/* is this the last of a logical block */
189*32148Sminshall {
190*32148Sminshall     register int c;
191*32148Sminshall     int origCount;
192*32148Sminshall     fd_set o;
193*32148Sminshall 
194*32148Sminshall     origCount = count;
195*32148Sminshall     FD_ZERO(&o);
196*32148Sminshall 
197*32148Sminshall     while (count) {
198*32148Sminshall 	if ((netobuf+sizeof netobuf - nfrontp) < 6) {
199*32148Sminshall 	    netflush();
200*32148Sminshall 	    while ((netobuf+sizeof netobuf - nfrontp) < 6) {
201*32148Sminshall 		FD_SET(net, &o);
202*32148Sminshall 		(void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
203*32148Sminshall 						(struct timeval *) 0);
204*32148Sminshall 		netflush();
205*32148Sminshall 	    }
206*32148Sminshall 	}
207*32148Sminshall 	c = *buffer++;
208*32148Sminshall 	count--;
209*32148Sminshall 	if (c == IAC) {
210*32148Sminshall 	    *nfrontp++ = IAC;
211*32148Sminshall 	    *nfrontp++ = IAC;
212*32148Sminshall 	} else {
213*32148Sminshall 	    *nfrontp++ = c;
214*32148Sminshall 	}
215*32148Sminshall     }
216*32148Sminshall 
217*32148Sminshall     if (done && !count) {
218*32148Sminshall 	*nfrontp++ = IAC;
219*32148Sminshall 	*nfrontp++ = EOR;
220*32148Sminshall 	netflush();		/* try to move along as quickly as ... */
221*32148Sminshall     }
222*32148Sminshall     return(origCount - count);
223*32148Sminshall }
224*32148Sminshall 
225*32148Sminshall /* DataToTerminal - queue up some data to go to terminal. */
226*32148Sminshall 
227*32148Sminshall int
228*32148Sminshall DataToTerminal(buffer, count)
229*32148Sminshall register char	*buffer;		/* where the data is */
230*32148Sminshall register int	count;			/* how much to send */
231*32148Sminshall {
232*32148Sminshall     int origCount;
233*32148Sminshall #if	defined(unix)
234*32148Sminshall     fd_set	o;
235*32148Sminshall 
236*32148Sminshall     FD_ZERO(&o);
237*32148Sminshall #endif	/* defined(unix) */
238*32148Sminshall     origCount = count;
239*32148Sminshall 
240*32148Sminshall     while (count) {
241*32148Sminshall 	if (tfrontp >= ttyobuf+sizeof ttyobuf) {
242*32148Sminshall 	    ttyflush();
243*32148Sminshall 	    while (tfrontp >= ttyobuf+sizeof ttyobuf) {
244*32148Sminshall #if	defined(unix)
245*32148Sminshall 		FD_SET(tout, &o);
246*32148Sminshall 		(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
247*32148Sminshall 						(struct timeval *) 0);
248*32148Sminshall #endif	/* defined(unix) */
249*32148Sminshall 		ttyflush();
250*32148Sminshall 	    }
251*32148Sminshall 	}
252*32148Sminshall 	*tfrontp++ = *buffer++;
253*32148Sminshall 	count--;
254*32148Sminshall     }
255*32148Sminshall     return(origCount - count);
256*32148Sminshall }
257*32148Sminshall 
258*32148Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty.
259*32148Sminshall  *			Note that we consider the buffer to run all the
260*32148Sminshall  *			way to the kernel (thus the select).
261*32148Sminshall  */
262*32148Sminshall 
263*32148Sminshall void
264*32148Sminshall EmptyTerminal()
265*32148Sminshall {
266*32148Sminshall #if	defined(unix)
267*32148Sminshall     fd_set	o;
268*32148Sminshall 
269*32148Sminshall     FD_ZERO(&o);
270*32148Sminshall #endif	/* defined(unix) */
271*32148Sminshall 
272*32148Sminshall     if (tfrontp == tbackp) {
273*32148Sminshall #if	defined(unix)
274*32148Sminshall 	FD_SET(tout, &o);
275*32148Sminshall 	(void) select(tout+1, (int *) 0, &o, (int *) 0,
276*32148Sminshall 			(struct timeval *) 0);	/* wait for TTLOWAT */
277*32148Sminshall #endif	/* defined(unix) */
278*32148Sminshall     } else {
279*32148Sminshall 	while (tfrontp != tbackp) {
280*32148Sminshall 	    ttyflush();
281*32148Sminshall #if	defined(unix)
282*32148Sminshall 	    FD_SET(tout, &o);
283*32148Sminshall 	    (void) select(tout+1, (int *) 0, &o, (int *) 0,
284*32148Sminshall 				(struct timeval *) 0);	/* wait for TTLOWAT */
285*32148Sminshall #endif	/* defined(unix) */
286*32148Sminshall 	}
287*32148Sminshall     }
288*32148Sminshall }
289*32148Sminshall 
290*32148Sminshall 
291*32148Sminshall /*
292*32148Sminshall  * Push3270 - Try to send data along the 3270 output (to screen) direction.
293*32148Sminshall  */
294*32148Sminshall 
295*32148Sminshall static int
296*32148Sminshall Push3270()
297*32148Sminshall {
298*32148Sminshall     int save = scc;
299*32148Sminshall 
300*32148Sminshall     if (scc) {
301*32148Sminshall 	if (Ifrontp+scc > Ibuf+sizeof Ibuf) {
302*32148Sminshall 	    if (Ibackp != Ibuf) {
303*32148Sminshall 		memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
304*32148Sminshall 		Ifrontp -= (Ibackp-Ibuf);
305*32148Sminshall 		Ibackp = Ibuf;
306*32148Sminshall 	    }
307*32148Sminshall 	}
308*32148Sminshall 	if (Ifrontp+scc < Ibuf+sizeof Ibuf) {
309*32148Sminshall 	    telrcv();
310*32148Sminshall 	}
311*32148Sminshall     }
312*32148Sminshall     return save != scc;
313*32148Sminshall }
314*32148Sminshall 
315*32148Sminshall 
316*32148Sminshall /*
317*32148Sminshall  * Finish3270 - get the last dregs of 3270 data out to the terminal
318*32148Sminshall  *		before quitting.
319*32148Sminshall  */
320*32148Sminshall 
321*32148Sminshall static void
322*32148Sminshall Finish3270()
323*32148Sminshall {
324*32148Sminshall     while (Push3270() || !DoTerminalOutput()) {
325*32148Sminshall #if	defined(unix)
326*32148Sminshall 	HaveInput = 0;
327*32148Sminshall #endif	/* defined(unix) */
328*32148Sminshall 	;
329*32148Sminshall     }
330*32148Sminshall }
331*32148Sminshall 
332*32148Sminshall 
333*32148Sminshall /* StringToTerminal - output a null terminated string to the terminal */
334*32148Sminshall 
335*32148Sminshall void
336*32148Sminshall StringToTerminal(s)
337*32148Sminshall char *s;
338*32148Sminshall {
339*32148Sminshall     int count;
340*32148Sminshall 
341*32148Sminshall     count = strlen(s);
342*32148Sminshall     if (count) {
343*32148Sminshall 	(void) DataToTerminal(s, count);	/* we know it always goes... */
344*32148Sminshall     }
345*32148Sminshall }
346*32148Sminshall 
347*32148Sminshall 
348*32148Sminshall #if	((!defined(NOT43)) || defined(PUTCHAR))
349*32148Sminshall /* _putchar - output a single character to the terminal.  This name is so that
350*32148Sminshall  *	curses(3x) can call us to send out data.
351*32148Sminshall  */
352*32148Sminshall 
353*32148Sminshall void
354*32148Sminshall _putchar(c)
355*32148Sminshall char c;
356*32148Sminshall {
357*32148Sminshall     if (tfrontp >= ttyobuf+sizeof ttyobuf) {
358*32148Sminshall 	(void) DataToTerminal(&c, 1);
359*32148Sminshall     } else {
360*32148Sminshall 	*tfrontp++ = c;		/* optimize if possible. */
361*32148Sminshall     }
362*32148Sminshall }
363*32148Sminshall #endif	/* ((!defined(NOT43)) || defined(PUTCHAR)) */
364*32148Sminshall #endif	/* defined(TN3270) */
365