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