xref: /original-bsd/usr.bin/telnet/tn3270.c (revision 00a25f5a)
1 /*
2  * Copyright (c) 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)tn3270.c	8.2 (Berkeley) 05/30/95";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 #include <arpa/telnet.h>
14 
15 #include "general.h"
16 
17 #include "defines.h"
18 #include "ring.h"
19 #include "externs.h"
20 #include "fdset.h"
21 
22 #if	defined(TN3270)
23 
24 #include "../ctlr/screen.h"
25 #include "../general/globals.h"
26 
27 #include "../sys_curses/telextrn.h"
28 #include "../ctlr/externs.h"
29 
30 #if	defined(unix)
31 int
32 	HaveInput,		/* There is input available to scan */
33 	cursesdata,		/* Do we dump curses data? */
34 	sigiocount;		/* Number of times we got a SIGIO */
35 
36 char	tline[200];
37 char	*transcom = 0;	/* transparent mode command (default: none) */
38 #endif	/* defined(unix) */
39 
40 char	Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
41 
42 static char	sb_terminal[] = { IAC, SB,
43 			TELOPT_TTYPE, TELQUAL_IS,
44 			'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
45 			IAC, SE };
46 #define	SBTERMMODEL	13
47 
48 static int
49 	Sent3270TerminalType;	/* Have we said we are a 3270? */
50 
51 #endif	/* defined(TN3270) */
52 
53 
54     void
55 init_3270()
56 {
57 #if	defined(TN3270)
58 #if	defined(unix)
59     HaveInput = 0;
60     sigiocount = 0;
61 #endif	/* defined(unix) */
62     Sent3270TerminalType = 0;
63     Ifrontp = Ibackp = Ibuf;
64     init_ctlr();		/* Initialize some things */
65     init_keyboard();
66     init_screen();
67     init_system();
68 #endif	/* defined(TN3270) */
69 }
70 
71 
72 #if	defined(TN3270)
73 
74 /*
75  * DataToNetwork - queue up some data to go to network.  If "done" is set,
76  * then when last byte is queued, we add on an IAC EOR sequence (so,
77  * don't call us with "done" until you want that done...)
78  *
79  * We actually do send all the data to the network buffer, since our
80  * only client needs for us to do that.
81  */
82 
83     int
84 DataToNetwork(buffer, count, done)
85     register char *buffer;	/* where the data is */
86     register int  count;	/* how much to send */
87     int		  done;		/* is this the last of a logical block */
88 {
89     register int loop, c;
90     int origCount;
91 
92     origCount = count;
93 
94     while (count) {
95 	/* If not enough room for EORs, IACs, etc., wait */
96 	if (NETROOM() < 6) {
97 	    fd_set o;
98 
99 	    FD_ZERO(&o);
100 	    netflush();
101 	    while (NETROOM() < 6) {
102 		FD_SET(net, &o);
103 		(void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
104 						(struct timeval *) 0);
105 		netflush();
106 	    }
107 	}
108 	c = ring_empty_count(&netoring);
109 	if (c > count) {
110 	    c = count;
111 	}
112 	loop = c;
113 	while (loop) {
114 	    if (((unsigned char)*buffer) == IAC) {
115 		break;
116 	    }
117 	    buffer++;
118 	    loop--;
119 	}
120 	if ((c = c-loop)) {
121 	    ring_supply_data(&netoring, buffer-c, c);
122 	    count -= c;
123 	}
124 	if (loop) {
125 	    NET2ADD(IAC, IAC);
126 	    count--;
127 	    buffer++;
128 	}
129     }
130 
131     if (done) {
132 	NET2ADD(IAC, EOR);
133 	netflush();		/* try to move along as quickly as ... */
134     }
135     return(origCount - count);
136 }
137 
138 
139 #if	defined(unix)
140     void
141 inputAvailable(signo)
142 	int signo;
143 {
144     HaveInput = 1;
145     sigiocount++;
146 }
147 #endif	/* defined(unix) */
148 
149     void
150 outputPurge()
151 {
152     (void) ttyflush(1);
153 }
154 
155 
156 /*
157  * The following routines are places where the various tn3270
158  * routines make calls into telnet.c.
159  */
160 
161 /*
162  * DataToTerminal - queue up some data to go to terminal.
163  *
164  * Note: there are people who call us and depend on our processing
165  * *all* the data at one time (thus the select).
166  */
167 
168     int
169 DataToTerminal(buffer, count)
170     register char	*buffer;		/* where the data is */
171     register int	count;			/* how much to send */
172 {
173     register int c;
174     int origCount;
175 
176     origCount = count;
177 
178     while (count) {
179 	if (TTYROOM() == 0) {
180 #if	defined(unix)
181 	    fd_set o;
182 
183 	    FD_ZERO(&o);
184 #endif	/* defined(unix) */
185 	    (void) ttyflush(0);
186 	    while (TTYROOM() == 0) {
187 #if	defined(unix)
188 		FD_SET(tout, &o);
189 		(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
190 						(struct timeval *) 0);
191 #endif	/* defined(unix) */
192 		(void) ttyflush(0);
193 	    }
194 	}
195 	c = TTYROOM();
196 	if (c > count) {
197 	    c = count;
198 	}
199 	ring_supply_data(&ttyoring, buffer, c);
200 	count -= c;
201 	buffer += c;
202     }
203     return(origCount);
204 }
205 
206 
207 /*
208  * Push3270 - Try to send data along the 3270 output (to screen) direction.
209  */
210 
211     int
212 Push3270()
213 {
214     int save = ring_full_count(&netiring);
215 
216     if (save) {
217 	if (Ifrontp+save > Ibuf+sizeof Ibuf) {
218 	    if (Ibackp != Ibuf) {
219 		memmove(Ibuf, Ibackp, Ifrontp-Ibackp);
220 		Ifrontp -= (Ibackp-Ibuf);
221 		Ibackp = Ibuf;
222 	    }
223 	}
224 	if (Ifrontp+save < Ibuf+sizeof Ibuf) {
225 	    (void)telrcv();
226 	}
227     }
228     return save != ring_full_count(&netiring);
229 }
230 
231 
232 /*
233  * Finish3270 - get the last dregs of 3270 data out to the terminal
234  *		before quitting.
235  */
236 
237     void
238 Finish3270()
239 {
240     while (Push3270() || !DoTerminalOutput()) {
241 #if	defined(unix)
242 	HaveInput = 0;
243 #endif	/* defined(unix) */
244 	;
245     }
246 }
247 
248 
249 /* StringToTerminal - output a null terminated string to the terminal */
250 
251     void
252 StringToTerminal(s)
253     char *s;
254 {
255     int count;
256 
257     count = strlen(s);
258     if (count) {
259 	(void) DataToTerminal(s, count);	/* we know it always goes... */
260     }
261 }
262 
263 
264 #if	((!defined(NOT43)) || defined(PUTCHAR))
265 /* _putchar - output a single character to the terminal.  This name is so that
266  *	curses(3x) can call us to send out data.
267  */
268 
269     void
270 _putchar(c)
271     char c;
272 {
273 #if	defined(sun)		/* SunOS 4.0 bug */
274     c &= 0x7f;
275 #endif	/* defined(sun) */
276     if (cursesdata) {
277 	Dump('>', &c, 1);
278     }
279     if (!TTYROOM()) {
280 	(void) DataToTerminal(&c, 1);
281     } else {
282 	TTYADD(c);
283     }
284 }
285 #endif	/* ((!defined(NOT43)) || defined(PUTCHAR)) */
286 
287     void
288 SetIn3270()
289 {
290     if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
291 		&& my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
292 	if (!In3270) {
293 	    In3270 = 1;
294 	    Init3270();		/* Initialize 3270 functions */
295 	    /* initialize terminal key mapping */
296 	    InitTerminal();	/* Start terminal going */
297 	    setconnmode(0);
298 	}
299     } else {
300 	if (In3270) {
301 	    StopScreen(1);
302 	    In3270 = 0;
303 	    Stop3270();		/* Tell 3270 we aren't here anymore */
304 	    setconnmode(0);
305 	}
306     }
307 }
308 
309 /*
310  * tn3270_ttype()
311  *
312  *	Send a response to a terminal type negotiation.
313  *
314  *	Return '0' if no more responses to send; '1' if a response sent.
315  */
316 
317     int
318 tn3270_ttype()
319 {
320     /*
321      * Try to send a 3270 type terminal name.  Decide which one based
322      * on the format of our screen, and (in the future) color
323      * capaiblities.
324      */
325     InitTerminal();		/* Sets MaxNumberColumns, MaxNumberLines */
326     if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
327 	Sent3270TerminalType = 1;
328 	if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
329 	    MaxNumberLines = 27;
330 	    MaxNumberColumns = 132;
331 	    sb_terminal[SBTERMMODEL] = '5';
332 	} else if (MaxNumberLines >= 43) {
333 	    MaxNumberLines = 43;
334 	    MaxNumberColumns = 80;
335 	    sb_terminal[SBTERMMODEL] = '4';
336 	} else if (MaxNumberLines >= 32) {
337 	    MaxNumberLines = 32;
338 	    MaxNumberColumns = 80;
339 	    sb_terminal[SBTERMMODEL] = '3';
340 	} else {
341 	    MaxNumberLines = 24;
342 	    MaxNumberColumns = 80;
343 	    sb_terminal[SBTERMMODEL] = '2';
344 	}
345 	NumberLines = 24;		/* before we start out... */
346 	NumberColumns = 80;
347 	ScreenSize = NumberLines*NumberColumns;
348 	if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
349 	    ExitString("Programming error:  MAXSCREENSIZE too small.\n",
350 								1);
351 	    /*NOTREACHED*/
352 	}
353 	printsub('>', sb_terminal+2, sizeof sb_terminal-2);
354 	ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
355 	return 1;
356     } else {
357 	return 0;
358     }
359 }
360 
361 #if	defined(unix)
362 	int
363 settranscom(argc, argv)
364 	int argc;
365 	char *argv[];
366 {
367 	int i;
368 
369 	if (argc == 1 && transcom) {
370 	   transcom = 0;
371 	}
372 	if (argc == 1) {
373 	   return 1;
374 	}
375 	transcom = tline;
376 	(void) strcpy(transcom, argv[1]);
377 	for (i = 2; i < argc; ++i) {
378 	    (void) strcat(transcom, " ");
379 	    (void) strcat(transcom, argv[i]);
380 	}
381 	return 1;
382 }
383 #endif	/* defined(unix) */
384 
385 #endif	/* defined(TN3270) */
386